diff --git a/modules_core/com.etendoerp.reportvaluationstock/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStock.java b/modules_core/com.etendoerp.reportvaluationstock/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStock.java index faa0869f6..4a6a63dbe 100644 --- a/modules_core/com.etendoerp.reportvaluationstock/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStock.java +++ b/modules_core/com.etendoerp.reportvaluationstock/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStock.java @@ -101,7 +101,7 @@ protected JRDataSource getReportData(Map parameters) { return (JRFieldProviderDataSource) jrParams.get(PARAM_SUB_REPORT); } - private void buildData(VariablesSecureApp vars, String strDate, + protected void buildData(VariablesSecureApp vars, String strDate, String strOrganization, String strWarehouse, String strCategoryProduct, String strCurrencyId, boolean isWarehouseConsolidation, Map parameters) throws ServletException { ReportValuationStockData[] data; diff --git a/src-test/src/com/etendoerp/reportvaluationstock/ETRVSComponentProviderTest.java b/src-test/src/com/etendoerp/reportvaluationstock/ETRVSComponentProviderTest.java new file mode 100644 index 000000000..05e610dfc --- /dev/null +++ b/src-test/src/com/etendoerp/reportvaluationstock/ETRVSComponentProviderTest.java @@ -0,0 +1,79 @@ +package com.etendoerp.reportvaluationstock; + +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 org.junit.Before; +import org.junit.Test; +import org.openbravo.client.kernel.BaseComponentProvider; + +import java.util.List; +import java.util.HashMap; + +/** + * Unit tests for the {@link ETRVSComponentProvider} class. + *

+ * This class tests the behavior of the component provider methods, ensuring + * correct handling of global component resources and specific components. + *

+ */ +public class ETRVSComponentProviderTest { + + private ETRVSComponentProvider componentProvider; + + /** + * Sets up the test environment by initializing the component provider instance. + */ + @Before + public void setUp() { + componentProvider = new ETRVSComponentProvider(); + } + + /** + * Tests the {@link ETRVSComponentProvider(String, HashMap)} method. + *

+ * Ensures that the method returns null when provided with an arbitrary ID and empty parameters. + *

+ */ + @Test + public void testGetComponent() { + assertNull(componentProvider.getComponent("testId", new HashMap<>())); + } + + /** + * Tests the {@link ETRVSComponentProvider#getGlobalComponentResources()} method. + *

+ * Verifies that the method returns a non-null list containing a single valid resource. + *

+ */ + @Test + public void testGetGlobalComponentResources() { + List resources = componentProvider.getGlobalComponentResources(); + + assertNotNull(resources); + + assertEquals(1, resources.size()); + + BaseComponentProvider.ComponentResource resource = resources.get(0); + assertNotNull(resource); + + assertEquals( + "web/com.etendoerp.reportvaluationstock/js/etrvs-onchange.js", + resource.getPath() + ); + + } + + /** + * Tests that {@link ETRVSComponentProvider#getGlobalComponentResources()} returns a non-empty list. + *

+ * Ensures the presence of global component resources. + *

+ */ + @Test + public void testGetGlobalComponentResourcesNotEmpty() { + assertFalse(componentProvider.getGlobalComponentResources().isEmpty()); + } +} \ No newline at end of file diff --git a/src-test/src/com/etendoerp/reportvaluationstock/handler/CostingRuleUtilsTest.java b/src-test/src/com/etendoerp/reportvaluationstock/handler/CostingRuleUtilsTest.java new file mode 100644 index 000000000..5ce46d855 --- /dev/null +++ b/src-test/src/com/etendoerp/reportvaluationstock/handler/CostingRuleUtilsTest.java @@ -0,0 +1,102 @@ +package com.etendoerp.reportvaluationstock.handler; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import org.junit.Test; +import org.junit.Before; +import org.openbravo.dal.service.OBQuery; +import org.openbravo.model.common.enterprise.Organization; +import org.openbravo.dal.service.OBDal; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.openbravo.model.materialmgmt.cost.CostingRule; + +import java.lang.reflect.Method; + +/** + * Test class for CostingRuleUtils, which verifies the logic related + * to the calculation of costing rules based on organizations. + */ +public class CostingRuleUtilsTest { + + private Organization mockOrganization; + private OBDal mockOBDal; + private Method getLEsCostingAlgortithmMethod; + + /** + * Sets up the initial state required for the tests. Prepare mocks and retrieves + * the reflected method from ReportValuationStock for testing purposes. + * + * @throws Exception if an error occurs during the setup. + */ + @Before + public void setUp() throws Exception { + getLEsCostingAlgortithmMethod = ReportValuationStock.class.getDeclaredMethod("getLEsCostingAlgortithm", Organization.class); + getLEsCostingAlgortithmMethod.setAccessible(true); + + mockOrganization = Mockito.mock(Organization.class); + mockOBDal = Mockito.mock(OBDal.class); + } + + /** + * Tests the getLEsCostingAlgortithm method with a valid organization. Verifies that + * the method returns the expected costing rule when provided with correct data. + * + * @throws Exception if an error occurs during the test execution. + */ + @Test + public void testGetLEsCostingAlgortithmWithValidOrganization() throws Exception { + String orgId = "TEST_ORG_ID"; + CostingRule expectedRule = Mockito.mock(CostingRule.class); + + Mockito.when(mockOrganization.getId()).thenReturn(orgId); + + try (MockedStatic mockedStatic = Mockito.mockStatic(OBDal.class)) { + mockedStatic.when(OBDal::getReadOnlyInstance).thenReturn(mockOBDal); + + OBQuery mockQuery = Mockito.mock(OBQuery.class); + Mockito.when(mockOBDal.createQuery(Mockito.eq(CostingRule.class), Mockito.anyString())) + .thenReturn(mockQuery); + Mockito.when(mockQuery.setNamedParameter(Mockito.eq("orgId"), Mockito.eq(orgId))) + .thenReturn(mockQuery); + Mockito.when(mockQuery.setMaxResult(1)).thenReturn(mockQuery); + Mockito.when(mockQuery.uniqueResult()).thenReturn(expectedRule); + + CostingRule result = (CostingRule) getLEsCostingAlgortithmMethod.invoke(null, mockOrganization); + + assertNotNull("El resultado no debería ser null", result); + assertEquals("El resultado debería ser el CostingRule esperado", expectedRule, result); + } + } + + /** + * Tests the getLEsCostingAlgortithm method when no costing rules are found. + * Verifies that the method returns null when no results are available. + * + * @throws Exception if an error occurs during the test execution. + */ + @Test + public void testGetLEsCostingAlgortithmNoRulesFound() throws Exception { + String orgId = "TEST_ORG_ID"; + + Mockito.when(mockOrganization.getId()).thenReturn(orgId); + + try (MockedStatic mockedStatic = Mockito.mockStatic(OBDal.class)) { + mockedStatic.when(OBDal::getReadOnlyInstance).thenReturn(mockOBDal); + + OBQuery mockQuery = Mockito.mock(OBQuery.class); + Mockito.when(mockOBDal.createQuery(Mockito.eq(CostingRule.class), Mockito.anyString())) + .thenReturn(mockQuery); + Mockito.when(mockQuery.setNamedParameter(Mockito.eq("orgId"), Mockito.eq(orgId))) + .thenReturn(mockQuery); + Mockito.when(mockQuery.setMaxResult(1)).thenReturn(mockQuery); + Mockito.when(mockQuery.uniqueResult()).thenReturn(null); + + CostingRule result = (CostingRule) getLEsCostingAlgortithmMethod.invoke(null, mockOrganization); + + assertNull("El resultado debería ser null cuando no se encuentran reglas", result); + } + } +} diff --git a/src-test/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStockAddParametersTest.java b/src-test/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStockAddParametersTest.java new file mode 100644 index 000000000..b471cd39a --- /dev/null +++ b/src-test/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStockAddParametersTest.java @@ -0,0 +1,146 @@ +package com.etendoerp.reportvaluationstock.handler; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import javax.servlet.ServletException; + +import org.codehaus.jettison.json.JSONObject; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.junit.MockitoJUnitRunner; +import org.openbravo.base.model.domaintype.DateDomainType; +import org.openbravo.base.secureApp.VariablesSecureApp; +import org.openbravo.base.session.OBPropertiesProvider; +import org.openbravo.client.application.ApplicationConstants; +import org.openbravo.client.application.ReportDefinition; +import org.openbravo.client.kernel.RequestContext; +import org.openbravo.dal.core.OBContext; +import org.openbravo.erpCommon.utility.OBMessageUtils; + +@RunWith(MockitoJUnitRunner.class) +public class ReportValuationStockAddParametersTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Mock + private ReportDefinition mockProcess; + + @Mock + private RequestContext mockRequestContext; + + @Mock + private VariablesSecureApp mockVars; + + @Mock + private OBPropertiesProvider mockPropertiesProvider; + + @Mock + private Properties mockProperties; + + private MockedStatic mockedRequestContext; + private MockedStatic mockedPropertiesProvider; + private MockedStatic mockedOBContext; + private MockedStatic mockedOBMessageUtils; + + private ReportValuationStock reportValuationStock; + + private static final String TEST_ORG_ID = "testOrgId"; + private static final String TEST_WAREHOUSE_ID = "testWarehouseId"; + private static final String TEST_CATEGORY_ID = "testCategoryId"; + private static final String TEST_CURRENCY_ID = "testCurrencyId"; + private static final String TEST_DATE = "2024-01-01"; + + @Before + public void setUp() throws ServletException { + reportValuationStock = spy(new ReportValuationStock()); + + mockedRequestContext = mockStatic(RequestContext.class); + mockedPropertiesProvider = mockStatic(OBPropertiesProvider.class); + mockedOBContext = mockStatic(OBContext.class); + mockedOBMessageUtils = mockStatic(OBMessageUtils.class); + + mockedRequestContext.when(RequestContext::get).thenReturn(mockRequestContext); + mockedPropertiesProvider.when(OBPropertiesProvider::getInstance).thenReturn(mockPropertiesProvider); + + mockedOBMessageUtils.when(() -> OBMessageUtils.translateError(anyString())) + .thenReturn(null); + mockedOBMessageUtils.when(() -> OBMessageUtils.messageBD(anyString())) + .thenReturn("Test Message"); + + when(mockRequestContext.getVariablesSecureApp()).thenReturn(mockVars); + when(mockPropertiesProvider.getOpenbravoProperties()).thenReturn(mockProperties); + when(mockProperties.getProperty("dateFormat.java")).thenReturn("yyyy-MM-dd"); + + doNothing().when(reportValuationStock).buildData( + any(VariablesSecureApp.class), + anyString(), + anyString(), + anyString(), + anyString(), + anyString(), + any(Boolean.class), + any(Map.class) + ); + } + + @After + public void tearDown() { + if (mockedRequestContext != null) { + mockedRequestContext.close(); + } + if (mockedPropertiesProvider != null) { + mockedPropertiesProvider.close(); + } + if (mockedOBContext != null) { + mockedOBContext.close(); + } + if (mockedOBMessageUtils != null) { + mockedOBMessageUtils.close(); + } + } + + @Test + public void testAddAdditionalParametersValidInput() throws Exception { + Map parameters = new HashMap<>(); + JSONObject jsonContent = new JSONObject(); + JSONObject params = new JSONObject(); + + params.put("AD_Org_ID", TEST_ORG_ID); + params.put("M_Warehouse_ID", TEST_WAREHOUSE_ID); + params.put("WarehouseConsolidation", true); + params.put("M_Product_Category_ID", TEST_CATEGORY_ID); + params.put("C_Currency_ID", TEST_CURRENCY_ID); + params.put("Date", TEST_DATE); + + jsonContent.put("_params", params); + jsonContent.put(ApplicationConstants.BUTTON_VALUE, "PDF"); + + mock(DateDomainType.class); + + reportValuationStock.addAdditionalParameters(mockProcess, jsonContent, parameters); + + assertNotNull("Parameters should not be null", parameters); + assertEquals("PDF", parameters.get("OUTPUT_FORMAT")); + } + + +} \ No newline at end of file diff --git a/src-test/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStockBuildDataTest.java b/src-test/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStockBuildDataTest.java new file mode 100644 index 000000000..f386c6cc4 --- /dev/null +++ b/src-test/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStockBuildDataTest.java @@ -0,0 +1,155 @@ +package com.etendoerp.reportvaluationstock.handler; + +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.servlet.ServletException; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.junit.MockitoJUnitRunner; +import org.openbravo.base.secureApp.VariablesSecureApp; +import org.openbravo.dal.core.OBContext; +import org.openbravo.dal.security.OrganizationStructureProvider; +import org.openbravo.dal.service.OBDal; +import org.openbravo.model.ad.system.Client; +import org.openbravo.model.common.enterprise.Organization; +import org.openbravo.service.db.DalConnectionProvider; +import org.openbravo.erpCommon.utility.OBError; +import org.openbravo.erpCommon.utility.OBMessageUtils; + +/** + * Test class for ReportValuationStock, verifying the behavior of the + * buildData method under various scenarios. + */ +@RunWith(MockitoJUnitRunner.class) +public class ReportValuationStockBuildDataTest { + + /** + * Rule to handle expected exceptions in test cases. + */ + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @InjectMocks + private ReportValuationStock reportValuationStock; + + @Mock + private VariablesSecureApp vars; + + @Mock + private Organization mockOrg; + + @Mock + private Client mockClient; + + @Mock + private OrganizationStructureProvider mockOsp; + + private Method buildDataMethod; + private static final String TEST_DATE = "2024-01-01"; + private static final String TEST_ORG_ID = "testOrgId"; + private static final String TEST_WAREHOUSE_ID = "testWarehouseId"; + private static final String TEST_CATEGORY_ID = "testCategoryId"; + private static final String TEST_CURRENCY_ID = "testCurrencyId"; + private static final String TEST_CLIENT_ID = "testClientId"; + + /** + * Sets up the initial state required for the tests. Prepare mocks and retrieves + * the reflected buildData method for testing. + * + * @throws Exception if an error occurs during the setup. + */ + @Before + public void setUp() throws Exception { + buildDataMethod = ReportValuationStock.class.getDeclaredMethod( + "buildData", + VariablesSecureApp.class, + String.class, + String.class, + String.class, + String.class, + String.class, + boolean.class, + Map.class + ); + buildDataMethod.setAccessible(true); + + when(mockClient.getId()).thenReturn(TEST_CLIENT_ID); + + Set orgTree = new HashSet<>(); + orgTree.add(TEST_ORG_ID); + } + + /** + * Tests the buildData method when the legal entity is null. Verifies that a + * ServletException is thrown with the expected error message. + */ + @Test + public void testBuildDataWithNullLegalEntity() { + Map parameters = new HashMap<>(); + + try (MockedStatic obDalMock = mockStatic(OBDal.class); + MockedStatic obContextMock = mockStatic(OBContext.class); + MockedStatic connectionProviderMock = mockStatic(DalConnectionProvider.class); + MockedStatic obMessageUtilsMock = mockStatic(OBMessageUtils.class)) { + + OBDal mockOBDal = mock(OBDal.class); + obDalMock.when(OBDal::getReadOnlyInstance).thenReturn(mockOBDal); + + OBContext mockContext = mock(OBContext.class); + when(mockContext.getCurrentClient()).thenReturn(mockClient); + when(mockContext.getOrganizationStructureProvider(anyString())).thenReturn(mockOsp); + obContextMock.when(OBContext::getOBContext).thenReturn(mockContext); + + DalConnectionProvider mockProvider = mock(DalConnectionProvider.class); + connectionProviderMock.when(DalConnectionProvider::getReadOnlyConnectionProvider) + .thenReturn(mockProvider); + + when(mockOBDal.get(eq(Organization.class), anyString())).thenReturn(mockOrg); + when(mockOsp.getLegalEntity(any(Organization.class))).thenReturn(null); + + OBError mockError = mock(OBError.class); + when(mockError.getMessage()).thenReturn("WarehouseNotInLE"); + obMessageUtilsMock.when(() -> OBMessageUtils.messageBD(anyString())) + .thenReturn("WarehouseNotInLE"); + obMessageUtilsMock.when(() -> OBMessageUtils.translateError(anyString())) + .thenReturn(mockError); + + try { + buildDataMethod.invoke( + reportValuationStock, + vars, + TEST_DATE, + TEST_ORG_ID, + TEST_WAREHOUSE_ID, + TEST_CATEGORY_ID, + TEST_CURRENCY_ID, + false, + parameters + ); + } catch (Exception e) { + assertTrue("Expected ServletException", e.getCause() instanceof ServletException); + assertTrue("Expected correct error message", + e.getCause().getMessage().contains("WarehouseNotInLE")); + } + } + } +} diff --git a/src-test/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStockCostTypeTest.java b/src-test/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStockCostTypeTest.java new file mode 100644 index 000000000..237185e42 --- /dev/null +++ b/src-test/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStockCostTypeTest.java @@ -0,0 +1,135 @@ +package com.etendoerp.reportvaluationstock.handler; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.when; + +import java.lang.reflect.Method; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.openbravo.costing.AverageAlgorithm; +import org.openbravo.costing.StandardAlgorithm; +import org.openbravo.model.materialmgmt.cost.CostingAlgorithm; + +/** + * Unit tests for the cost type determination logic in the {@link ReportValuationStock} class. + * This class verifies the behavior of the `getCostType` method when handling + * different costing algorithms. + */ +@RunWith(MockitoJUnitRunner.class) +public class ReportValuationStockCostTypeTest { + + @InjectMocks + private ReportValuationStock reportValuationStock; + + @Mock + private CostingAlgorithm mockCostingAlgorithm; + + private Method getCostTypeMethod; + + /** + * Sets up the test environment by initializing the required objects + * and preparing the `getCostType` method for reflective invocation. + * + * @throws Exception if reflection setup fails + */ + @Before + public void setUp() throws Exception { + getCostTypeMethod = ReportValuationStock.class.getDeclaredMethod( + "getCostType", + CostingAlgorithm.class + ); + getCostTypeMethod.setAccessible(true); + } + + /** + * Tests the `getCostType` method for a costing algorithm of type {@link AverageAlgorithm}. + * + * @throws Exception if the method invocation or mock setup fails + */ + @Test + public void testGetCostTypeWithAverageAlgorithm() throws Exception { + when(mockCostingAlgorithm.getJavaClassName()) + .thenReturn(TestAverageAlgorithm.class.getName()); + + String result = (String) getCostTypeMethod.invoke( + reportValuationStock, + mockCostingAlgorithm + ); + + assertEquals("Should return AVA for Average Algorithm", "'AVA'", result); + } + + /** + * Tests the `getCostType` method for a costing algorithm of type {@link StandardAlgorithm}. + * + * @throws Exception if the method invocation or mock setup fails + */ + @Test + public void testGetCostTypeWithStandardAlgorithm() throws Exception { + when(mockCostingAlgorithm.getJavaClassName()) + .thenReturn(TestStandardAlgorithm.class.getName()); + + String result = (String) getCostTypeMethod.invoke( + reportValuationStock, + mockCostingAlgorithm + ); + + assertEquals("Should return STA for Standard Algorithm", "'STA'", result); + } + + /** + * Tests the `getCostType` method for an unknown costing algorithm type. + * + * @throws Exception if the method invocation or mock setup fails + */ + @Test + public void testGetCostTypeWithUnknownAlgorithm() throws Exception { + when(mockCostingAlgorithm.getJavaClassName()) + .thenReturn(String.class.getName()); + + String result = (String) getCostTypeMethod.invoke( + reportValuationStock, + mockCostingAlgorithm + ); + + assertNull("Should return null for unknown algorithm type", result); + } + + /** + * Tests the `getCostType` method when the provided class name does not exist. + * + * @throws Exception if the method invocation or mock setup fails + */ + @Test + public void testGetCostTypeWithNonexistentClass() throws Exception { + when(mockCostingAlgorithm.getJavaClassName()) + .thenReturn("com.nonexistent.Class"); + + String result = (String) getCostTypeMethod.invoke( + reportValuationStock, + mockCostingAlgorithm + ); + + assertNull("Should return null when class is not found", result); + } + + /** + * Mock implementation of the {@link AverageAlgorithm} for testing purposes. + */ + public static class TestAverageAlgorithm extends AverageAlgorithm { + // Empty class for testing only + } + + /** + * Mock implementation of the {@link StandardAlgorithm} for testing purposes. + */ + public static class TestStandardAlgorithm extends StandardAlgorithm { + // Empty class for testing only + } +} \ No newline at end of file diff --git a/src-test/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStockGetReportTest.java b/src-test/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStockGetReportTest.java new file mode 100644 index 000000000..9945de1b0 --- /dev/null +++ b/src-test/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStockGetReportTest.java @@ -0,0 +1,215 @@ +package com.etendoerp.reportvaluationstock.handler; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +import org.codehaus.jettison.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.junit.MockitoJUnitRunner; +import org.openbravo.base.exception.OBException; +import org.openbravo.base.secureApp.VariablesSecureApp; +import org.openbravo.client.application.ReportDefinition; +import org.openbravo.database.ConnectionProvider; +import org.openbravo.erpCommon.utility.JRFieldProviderDataSource; +import org.openbravo.model.common.enterprise.Organization; + +import net.sf.jasperreports.engine.JRDataSource; + +/** + * Unit tests for the {@link ReportValuationStock} class. + * This class uses Mockito to mock dependencies and test different + * scenarios for the Report Valuation Stock functionality. + */ +@RunWith(MockitoJUnitRunner.class) +public class ReportValuationStockGetReportTest { + + @Mock + private VariablesSecureApp vars; + + @Mock + private ConnectionProvider readOnlyCP; + + @Mock + private Organization filterOrg; + + @Mock + private ReportDefinition mockProcess; + + @Mock + private ReportValuationStockData mockData; + + private ReportValuationStock reportValuationStock; + private Method getReportValuationStockDataMethod; + + private static final String TEST_DATE = "2024-01-01"; + private static final String TEST_CATEGORY = "TEST_CATEGORY"; + private static final String TEST_CURRENCY = "102"; + private static final String TEST_WAREHOUSE = "TEST_WAREHOUSE"; + private static final String TEST_ORG = "TEST_ORG"; + private static final String TEST_CLIENT = "TEST_CLIENT"; + private static final String TEST_LANGUAGE = "en_US"; + + /** + * Sets up the test environment by initializing the required objects + * and configuring mock behaviors. + * + * @throws Exception if reflection or setup fails + */ + @Before + public void setUp() throws Exception { + reportValuationStock = new ReportValuationStock(); + + getReportValuationStockDataMethod = ReportValuationStock.class.getDeclaredMethod( + "getReportValuationStockData", + VariablesSecureApp.class, String.class, String.class, String.class, + boolean.class, String.class, String.class, String.class, String.class, + ConnectionProvider.class, Organization.class, String.class, String.class, + String.class, String.class, String.class, String.class, String.class + ); + getReportValuationStockDataMethod.setAccessible(true); + + when(vars.getLanguage()).thenReturn(TEST_LANGUAGE); + } + + /** + * Tests the retrieval of report data with cost type enabled + * and no warehouse consolidation. + * + * @throws Exception if the method invocation or mocks fail + */ + @Test + public void testGetReportDataWithCostTypeAndNoWarehouseConsolidation() throws Exception { + ReportValuationStockData[] expectedData = new ReportValuationStockData[] { mockData }; + + try (MockedStatic mockedStatic = mockStatic(ReportValuationStockData.class)) { + mockedStatic.when(() -> ReportValuationStockData.select( + eq(readOnlyCP), anyString(), anyString(), anyString(), + anyString(), anyString(), anyString(), anyString(), + anyString(), anyString(), anyString(), anyString(), + anyString(), anyString(), anyString(), anyString()) + ).thenReturn(expectedData); + + ReportValuationStockData[] result = (ReportValuationStockData[]) getReportValuationStockDataMethod.invoke( + reportValuationStock, + vars, TEST_DATE, TEST_CATEGORY, TEST_CURRENCY, false, "processTime", + "N", "STA", TEST_WAREHOUSE, readOnlyCP, filterOrg, TEST_ORG, + "orgIds", TEST_ORG, TEST_CLIENT, "dateNext", "maxAggDate", "dateFormat" + ); + + assertNotNull("Result should not be null", result); + assertEquals("Should return expected data length", expectedData.length, result.length); + assertEquals("Should return expected data", expectedData[0], result[0]); + } + } + + /** + * Tests the retrieval of report data without cost type + * and with warehouse consolidation enabled. + * + * @throws Exception if the method invocation or mocks fail + */ + @Test + public void testGetReportDataWithoutCostTypeAndWithWarehouseConsolidation() throws Exception { + ReportValuationStockData[] expectedData = new ReportValuationStockData[] { mockData }; + + try (MockedStatic mockedStatic = mockStatic(ReportValuationStockData.class)) { + mockedStatic.when(() -> ReportValuationStockData.selectClusteredByWarehouseWithoutCost( + eq(readOnlyCP), anyString(), anyString(), anyString(), + anyString(), anyString(), anyString(), anyString(), + anyString(), anyString(), anyString()) + ).thenReturn(expectedData); + + ReportValuationStockData[] result = (ReportValuationStockData[]) getReportValuationStockDataMethod.invoke( + reportValuationStock, + vars, TEST_DATE, TEST_CATEGORY, TEST_CURRENCY, true, "processTime", + "N", null, TEST_WAREHOUSE, readOnlyCP, filterOrg, TEST_ORG, + "orgIds", TEST_ORG, TEST_CLIENT, "dateNext", "maxAggDate", "dateFormat" + ); + + assertNotNull("Result should not be null", result); + assertEquals("Should return expected data length", expectedData.length, result.length); + assertEquals("Should return expected data", expectedData[0], result[0]); + } + } + + /** + * Tests the retrieval of report data without cost type + * and no warehouse consolidation. + * + * @throws Exception if the method invocation or mocks fail + */ + @Test + public void testGetReportDataWithoutCostTypeAndNoWarehouseConsolidation() throws Exception { + ReportValuationStockData[] expectedData = new ReportValuationStockData[] { mockData }; + + try (MockedStatic mockedStatic = mockStatic(ReportValuationStockData.class)) { + mockedStatic.when(() -> ReportValuationStockData.selectWithoutCost( + eq(readOnlyCP), anyString(), anyString(), anyString(), + anyString(), anyString(), anyString(), anyString(), + anyString(), anyString(), anyString()) + ).thenReturn(expectedData); + + ReportValuationStockData[] result = (ReportValuationStockData[]) getReportValuationStockDataMethod.invoke( + reportValuationStock, + vars, TEST_DATE, TEST_CATEGORY, TEST_CURRENCY, false, "processTime", + "N", null, TEST_WAREHOUSE, readOnlyCP, filterOrg, TEST_ORG, + "orgIds", TEST_ORG, TEST_CLIENT, "dateNext", "maxAggDate", "dateFormat" + ); + + assertNotNull("Result should not be null", result); + assertEquals("Should return expected data length", expectedData.length, result.length); + assertEquals("Should return expected data", expectedData[0], result[0]); + } + } + + /** + * Tests the generation of report data using parameters + * provided in a map. + */ + @Test + public void testGetReportData() { + Map parameters = new HashMap<>(); + HashMap jasperParams = new HashMap<>(); + parameters.put("JASPER_REPORT_PARAMETERS", jasperParams); + + JRFieldProviderDataSource mockDataSource = mock(JRFieldProviderDataSource.class); + jasperParams.put("SUMMARY_DATASET", mockDataSource); + + JRDataSource result = reportValuationStock.getReportData(parameters); + + assertNotNull("Should return data source", result); + assertEquals("Should return correct data source", mockDataSource, result); + } + + /** + * Tests the addition of additional parameters to the report with + * an invalid date format, expecting an {@link OBException}. + * + * @throws Exception if JSON manipulation fails + */ + @Test(expected = OBException.class) + public void testAddAdditionalParametersInvalidDate() throws Exception { + Map parameters = new HashMap<>(); + JSONObject jsonContent = new JSONObject(); + JSONObject params = new JSONObject(); + + params.put("AD_Org_ID", "testOrgId"); + params.put("Date", "invalid-date"); + jsonContent.put("_params", params); + + reportValuationStock.addAdditionalParameters(mockProcess, jsonContent, parameters); + } +} \ No newline at end of file diff --git a/src-test/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStockParametersTest.java b/src-test/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStockParametersTest.java new file mode 100644 index 000000000..25d76d40e --- /dev/null +++ b/src-test/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStockParametersTest.java @@ -0,0 +1,136 @@ +package com.etendoerp.reportvaluationstock.handler; + +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +import java.util.HashMap; +import java.util.Map; + +import org.codehaus.jettison.json.JSONObject; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.junit.MockitoJUnitRunner; +import org.openbravo.base.exception.OBException; +import org.openbravo.base.secureApp.VariablesSecureApp; +import org.openbravo.base.session.OBPropertiesProvider; +import org.openbravo.client.application.ReportDefinition; +import org.openbravo.client.kernel.RequestContext; +import org.openbravo.erpCommon.utility.OBError; +import org.openbravo.erpCommon.utility.OBMessageUtils; + +/** + * Unit tests for the {@link ReportValuationStock} class. + * + *

This class is responsible for testing the functionality of the + * {@code addAdditionalParameters} method in the {@code ReportValuationStock} class. + * + *

Tests include scenarios for invalid dates and missing required parameters. + */ +@RunWith(MockitoJUnitRunner.class) +public class ReportValuationStockParametersTest { + + private static final String TEST_ORG_ID = "testOrgId"; + + + @Mock + private ReportDefinition mockProcess; + + @Mock + private RequestContext mockRequestContext; + + @Mock + private VariablesSecureApp mockVars; + + @Mock + private OBPropertiesProvider mockPropertiesProvider; + + + @Mock + private OBError mockError; + + private ReportValuationStock reportValuationStock; + private MockedStatic mockedRequestContext; + private MockedStatic mockedPropertiesProvider; + private MockedStatic mockedMessageUtils; + + /** + * Sets up the test environment by initializing mocks and static instances. + */ + @Before + public void setUp() { + reportValuationStock = new ReportValuationStock() { + }; + + mockedRequestContext = mockStatic(RequestContext.class); + mockedPropertiesProvider = mockStatic(OBPropertiesProvider.class); + mockedMessageUtils = mockStatic(OBMessageUtils.class); + + mockedRequestContext.when(RequestContext::get).thenReturn(mockRequestContext); + when(mockRequestContext.getVariablesSecureApp()).thenReturn(mockVars); + + mockedPropertiesProvider.when(OBPropertiesProvider::getInstance) + .thenReturn(mockPropertiesProvider); + + mockedMessageUtils.when(() -> OBMessageUtils.translateError(anyString())) + .thenReturn(mockError); + } + + /** + * Cleans up the mocked static instances after each test. + */ + @After + public void tearDown() { + if (mockedRequestContext != null) { + mockedRequestContext.close(); + } + if (mockedPropertiesProvider != null) { + mockedPropertiesProvider.close(); + } + if (mockedMessageUtils != null) { + mockedMessageUtils.close(); + } + } + + /** + * Tests the {@code addAdditionalParameters} method for invalid date format. + * + *

Expects an {@link OBException} to be thrown when the date format is invalid. + * + * @throws Exception if the test fails unexpectedly + */ + @Test(expected = OBException.class) + public void testAddAdditionalParametersInvalidDate() throws Exception { + Map parameters = new HashMap<>(); + JSONObject jsonContent = new JSONObject(); + JSONObject params = new JSONObject(); + + params.put("AD_Org_ID", TEST_ORG_ID); + params.put("Date", "invalid-date"); + jsonContent.put("_params", params); + + reportValuationStock.addAdditionalParameters(mockProcess, jsonContent, parameters); + } + + /** + * Tests the {@code addAdditionalParameters} method for missing required parameters. + * + *

Expects an {@link OBException} to be thrown when a required parameter is missing. + * + * @throws Exception if the test fails unexpectedly + */ + @Test(expected = OBException.class) + public void testAddAdditionalParametersMissingRequiredParameter() throws Exception { + Map parameters = new HashMap<>(); + JSONObject jsonContent = new JSONObject(); + JSONObject params = new JSONObject(); + + jsonContent.put("_params", params); + + reportValuationStock.addAdditionalParameters(mockProcess, jsonContent, parameters); + } +} \ No newline at end of file diff --git a/src-test/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStockPrintTest.java b/src-test/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStockPrintTest.java new file mode 100644 index 000000000..4309d1908 --- /dev/null +++ b/src-test/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStockPrintTest.java @@ -0,0 +1,221 @@ +package com.etendoerp.reportvaluationstock.handler; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +import java.lang.reflect.Method; +import java.text.DecimalFormat; +import java.util.HashMap; +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.junit.MockitoJUnitRunner; +import org.openbravo.base.secureApp.VariablesSecureApp; +import org.openbravo.erpCommon.utility.OBMessageUtils; +import org.openbravo.erpCommon.utility.Utility; +import org.openbravo.model.materialmgmt.cost.CostingAlgorithm; + +/** + * Unit tests for the {@link ReportValuationStock} class. + *

+ * This class validates the behavior of the {@code printReport} method, ensuring it correctly + * formats parameters, handles costing algorithms, and processes custom number formats. + *

+ */ + +@RunWith(MockitoJUnitRunner.class) +public class ReportValuationStockPrintTest { + + @InjectMocks + private ReportValuationStock reportValuationStock; + + @Mock + private VariablesSecureApp vars; + + @Mock + private CostingAlgorithm costingAlgorithm; + + private Method printReportMethod; + private static final String TEST_DATE = "2024-01-01"; + private static final String TEST_COST_TYPE = "AVA"; + private static final String TEST_ALGORITHM_NAME = "Average Algorithm"; + private static final String TEST_TRANSLATED_HEADER = "Translated Cost Header"; + private static final String TEST_TRANSLATED_VALUATION = "Translated Valuation Header"; + + /** + * Sets up the test environment by initializing mocks and reflective access to the method under test. + * + * @throws Exception if the method cannot be accessed. + */ + + @Before + public void setUp() throws Exception { + printReportMethod = ReportValuationStock.class.getDeclaredMethod( + "printReport", + VariablesSecureApp.class, + String.class, + ReportValuationStockData[].class, + String.class, + CostingAlgorithm.class, + Map.class + ); + printReportMethod.setAccessible(true); + + when(vars.getSessionValue("#AD_ReportDecimalSeparator")).thenReturn("."); + when(vars.getSessionValue("#AD_ReportGroupingSeparator")).thenReturn(","); + when(vars.getSessionValue("#AD_ReportNumberFormat")).thenReturn("#,##0.00"); + when(vars.getJavaDateFormat()).thenReturn("yyyy-MM-dd"); + + when(costingAlgorithm.getName()).thenReturn(TEST_ALGORITHM_NAME); + } + + /** + * Tests the {@code printReport} method with a defined costing algorithm. + *

+ * Validates that the method correctly processes headers and parameters + * when a costing algorithm is provided. + *

+ * + * @throws Exception if the method invocation fails. + */ + + @Test + public void testPrintReportWithCostingAlgorithm() throws Exception { + ReportValuationStockData[] testData = new ReportValuationStockData[0]; + Map parameters = new HashMap<>(); + DecimalFormat mockFormat = new DecimalFormat("#,##0.00"); + + try (MockedStatic obMessageUtilsMock = mockStatic(OBMessageUtils.class); + MockedStatic utilityMock = mockStatic(Utility.class)) { + + obMessageUtilsMock.when(() -> OBMessageUtils.messageBD("ValuedStockReport_CostHeader")) + .thenReturn("Cost Header @algorithm@"); + obMessageUtilsMock.when(() -> OBMessageUtils.messageBD("ValuedStockReport_ValuationHeader")) + .thenReturn("Valuation Header @algorithm@"); + obMessageUtilsMock.when(() -> OBMessageUtils.parseTranslation(anyString(), any())) + .thenReturn(TEST_TRANSLATED_HEADER) + .thenReturn(TEST_TRANSLATED_VALUATION); + + utilityMock.when(() -> Utility.getFormat(any(), anyString())).thenReturn(mockFormat); + + printReportMethod.invoke( + reportValuationStock, + vars, + TEST_DATE, + testData, + TEST_COST_TYPE, + costingAlgorithm, + parameters + ); + + assertNotNull("Parameters should not be null", parameters); + assertEquals("Should have correct cost header", + TEST_TRANSLATED_HEADER, parameters.get("ALG_COST")); + assertEquals("Should have correct valuation header", + TEST_TRANSLATED_VALUATION, parameters.get("SUM_ALG_COST")); + assertEquals("Should have correct title", + "Valued Stock Report", parameters.get("TITLE")); + assertEquals("Should have correct date", + TEST_DATE, parameters.get("DATE")); + assertNotNull("Should have number format", + parameters.get("NUMBERFORMAT")); + assertEquals("Should have correct decimal format", + mockFormat, parameters.get("COSTFORMAT")); + } + } + + /** + * Tests the {@code printReport} method without a costing algorithm. + *

+ * Confirms that the method correctly processes headers and parameters + * when no costing algorithm is provided. + *

+ * + * @throws Exception if the method invocation fails. + */ + + @Test + public void testPrintReportWithoutCostingAlgorithm() throws Exception { + ReportValuationStockData[] testData = new ReportValuationStockData[0]; + Map parameters = new HashMap<>(); + DecimalFormat mockFormat = new DecimalFormat("#,##0.00"); + + try (MockedStatic utilityMock = mockStatic(Utility.class)) { + utilityMock.when(() -> Utility.getFormat(any(), anyString())).thenReturn(mockFormat); + + printReportMethod.invoke( + reportValuationStock, + vars, + TEST_DATE, + testData, + null, + null, + parameters + ); + + assertNotNull("Parameters should not be null", parameters); + assertEquals("Should have empty cost header", + "", parameters.get("ALG_COST")); + assertEquals("Should have empty valuation header", + "", parameters.get("SUM_ALG_COST")); + assertEquals("Should have correct title", + "Valued Stock Report", parameters.get("TITLE")); + assertEquals("Should have correct date", + TEST_DATE, parameters.get("DATE")); + assertNotNull("Should have number format", + parameters.get("NUMBERFORMAT")); + assertEquals("Should have correct decimal format", + mockFormat, parameters.get("COSTFORMAT")); + } + } + + /** + * Tests the {@code printReport} method with custom number formats and separators. + *

+ * Ensures that the method correctly applies custom formatting settings for decimal + * and grouping separators. + *

+ * + * @throws Exception if the method invocation fails. + */ + + @Test + public void testPrintReportWithCustomFormats() throws Exception { + ReportValuationStockData[] testData = new ReportValuationStockData[0]; + Map parameters = new HashMap<>(); + DecimalFormat mockFormat = new DecimalFormat("#,##0.000"); + + when(vars.getSessionValue("#AD_ReportDecimalSeparator")).thenReturn(","); + when(vars.getSessionValue("#AD_ReportGroupingSeparator")).thenReturn("."); + when(vars.getSessionValue("#AD_ReportNumberFormat")).thenReturn("#,##0.000"); + + try (MockedStatic utilityMock = mockStatic(Utility.class)) { + utilityMock.when(() -> Utility.getFormat(any(), anyString())).thenReturn(mockFormat); + + printReportMethod.invoke( + reportValuationStock, + vars, + TEST_DATE, + testData, + TEST_COST_TYPE, + null, + parameters + ); + + assertNotNull("Parameters should not be null", parameters); + assertNotNull("Should have number format with custom separators", + parameters.get("NUMBERFORMAT")); + assertEquals("Should have correct decimal format", + mockFormat, parameters.get("COSTFORMAT")); + } + } +} \ No newline at end of file diff --git a/src-test/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStockSummaryTest.java b/src-test/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStockSummaryTest.java new file mode 100644 index 000000000..98a35f93a --- /dev/null +++ b/src-test/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStockSummaryTest.java @@ -0,0 +1,174 @@ +package com.etendoerp.reportvaluationstock.handler; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.junit.MockitoJUnitRunner; +import org.openbravo.data.FieldProvider; + +/** + * Unit tests for the {@link ReportValuationStock} class. + *

+ * This class validates the behavior of the {@code getSummaryProductCategories} method + * in various scenarios, including handling empty data, single category, multiple entries + * in the same category, and null costs. + *

+ */ + +@RunWith(MockitoJUnitRunner.class) +public class ReportValuationStockSummaryTest { + + @InjectMocks + private ReportValuationStock reportValuationStock; + + private Method getSummaryProductCategoriesMethod; + + /** + * Sets up the test environment by initializing reflective access to the method under test. + * + * @throws Exception if the method cannot be accessed. + */ + + @Before + public void setUp() throws Exception { + getSummaryProductCategoriesMethod = ReportValuationStock.class.getDeclaredMethod( + "getSummaryProductCategories", + ReportValuationStockData[].class + ); + getSummaryProductCategoriesMethod.setAccessible(true); + } + + /** + * Sets the value of a field in the target object using reflection. + * + * @param target the target object whose field is to be modified + * @param fieldName the name of the field to set + * @param value the value to assign to the field + * @throws Exception if the field cannot be accessed or set + */ + + private void setFieldValue(Object target, String fieldName, Object value) throws Exception { + Field field = target.getClass().getField(fieldName); + field.set(target, value); + } + + /** + * Tests the {@code getSummaryProductCategories} method with empty input data. + *

+ * Ensures that the method returns an empty result when provided with no data. + *

+ * + * @throws Exception if the method invocation fails. + */ + + @Test + public void testGetSummaryProductCategoriesWithEmptyData() throws Exception { + ReportValuationStockData[] data = new ReportValuationStockData[0]; + + FieldProvider[] result = (FieldProvider[]) getSummaryProductCategoriesMethod.invoke( + reportValuationStock, + (Object) data + ); + + assertNotNull("Result should not be null", result); + assertEquals("Empty data should return empty result", 0, result.length); + } + + /** + * Tests the {@code getSummaryProductCategories} method with a single data entry. + *

+ * Validates that the method correctly processes and returns data for one category. + *

+ * + * @throws Exception if the method invocation fails. + */ + + @Test + public void testGetSummaryProductCategoriesWithSingleCategory() throws Exception { + ReportValuationStockData singleData = new ReportValuationStockData(); + setFieldValue(singleData, "categoryName", "TestCategory"); + setFieldValue(singleData, "totalCost", "100.00"); + + ReportValuationStockData[] data = new ReportValuationStockData[] { singleData }; + + FieldProvider[] result = (FieldProvider[]) getSummaryProductCategoriesMethod.invoke( + reportValuationStock, + (Object) data + ); + + assertNotNull("Result should not be null", result); + assertEquals("Should contain one category", 1, result.length); + assertEquals("Should have correct category name", "TestCategory", + result[0].getField("category")); + assertEquals("Should have correct cost", "100.00", + result[0].getField("cost")); + } + + /** + * Tests the {@code getSummaryProductCategories} method with multiple entries in the same category. + *

+ * Verifies that the method aggregates costs correctly for a single category. + *

+ * + * @throws Exception if the method invocation fails. + */ + + @Test + public void testGetSummaryProductCategoriesWithMultipleEntriesSameCategory() throws Exception { + ReportValuationStockData data1 = new ReportValuationStockData(); + setFieldValue(data1, "categoryName", "TestCategory"); + setFieldValue(data1, "totalCost", "100.00"); + + ReportValuationStockData data2 = new ReportValuationStockData(); + setFieldValue(data2, "categoryName", "TestCategory"); + setFieldValue(data2, "totalCost", "50.00"); + + ReportValuationStockData[] data = new ReportValuationStockData[] { data1, data2 }; + + FieldProvider[] result = (FieldProvider[]) getSummaryProductCategoriesMethod.invoke( + reportValuationStock, + (Object) data + ); + + assertNotNull("Result should not be null", result); + assertEquals("Should contain one category", 1, result.length); + assertEquals("Category name should match", "TestCategory", + result[0].getField("category")); + assertEquals("Total cost should be summed correctly", "150.00", + result[0].getField("cost")); + } + + /** + * Tests the {@code getSummaryProductCategories} method with null cost values. + *

+ * Confirms that the method handles null costs by treating them as zero. + *

+ * + * @throws Exception if the method invocation fails. + */ + + @Test + public void testGetSummaryProductCategoriesWithNullCosts() throws Exception { + ReportValuationStockData nullCostData = new ReportValuationStockData(); + setFieldValue(nullCostData, "categoryName", "TestCategory"); + setFieldValue(nullCostData, "totalCost", null); + + ReportValuationStockData[] data = new ReportValuationStockData[] { nullCostData }; + + FieldProvider[] result = (FieldProvider[]) getSummaryProductCategoriesMethod.invoke( + reportValuationStock, + (Object) data + ); + + assertNotNull("Result should not be null", result); + assertEquals("Should contain one category", 1, result.length); + assertEquals("Cost should be zero for null values", "0", + result[0].getField("cost")); + } +} \ No newline at end of file diff --git a/src-test/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStockWarehousesTest.java b/src-test/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStockWarehousesTest.java new file mode 100644 index 000000000..d4ce4f53c --- /dev/null +++ b/src-test/src/com/etendoerp/reportvaluationstock/handler/ReportValuationStockWarehousesTest.java @@ -0,0 +1,165 @@ +package com.etendoerp.reportvaluationstock.handler; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.junit.MockitoJUnitRunner; +import org.openbravo.dal.core.OBContext; +import org.openbravo.dal.security.OrganizationStructureProvider; +import org.openbravo.dal.service.OBDal; +import org.hibernate.Session; +import org.hibernate.query.Query; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +/** + * Unit tests for the {@link ReportValuationStock} class. + *

+ * This class validates the behavior of the {@code getWarehouses} method in various scenarios, + * including cases with results and cases with no results. + *

+ */ +@RunWith(MockitoJUnitRunner.class) +public class ReportValuationStockWarehousesTest { + + private static final String CLIENT_ID = "testClient"; + private static final String ORG_ID = "testOrg"; + private static final String WAREHOUSE_ID_1 = "warehouse1"; + private static final String WAREHOUSE_ID_2 = "warehouse2"; + + @InjectMocks + private ReportValuationStock reportValuationStock; + + @Mock + private OBDal mockOBDal; + + @Mock + private Session mockSession; + + @Mock + private Query mockQuery; + + @Mock + private OBContext mockOBContext; + + @Mock + private OrganizationStructureProvider mockOsp; + + private Method getWarehousesMethod; + + /** + * Sets up the test environment by initializing mocks and reflective access to the method under test. + * + * @throws Exception if the method cannot be accessed. + */ + @Before + public void setUp() throws Exception { + getWarehousesMethod = ReportValuationStock.class.getDeclaredMethod( + "getWarehouses", + String.class, + String.class + ); + getWarehousesMethod.setAccessible(true); + } + + /** + * Tests the {@code getWarehouses} method with valid inputs, expecting a non-empty list of results. + * + * @throws Exception if the method invocation fails. + */ + @Test + public void testGetWarehousesWithResults() throws Exception { + List expectedOrgIds = Arrays.asList("org1", "org2"); + List expectedWarehouseIds = Arrays.asList(WAREHOUSE_ID_1, WAREHOUSE_ID_2); + + try (MockedStatic obContextMock = mockStatic(OBContext.class); + MockedStatic obDalMock = mockStatic(OBDal.class)) { + + obContextMock.when(OBContext::getOBContext).thenReturn(mockOBContext); + when(mockOBContext.getOrganizationStructureProvider(CLIENT_ID)) + .thenReturn(mockOsp); + when(mockOsp.getNaturalTree(ORG_ID)) + .thenReturn(Set.copyOf(expectedOrgIds)); + + obDalMock.when(OBDal::getReadOnlyInstance).thenReturn(mockOBDal); + when(mockOBDal.getSession()).thenReturn(mockSession); + when(mockSession.createQuery(anyString(), eq(String.class))) + .thenReturn(mockQuery); + when(mockQuery.setParameterList((String) eq("orgIds"), (Collection) any())) + .thenReturn(mockQuery); + when(mockQuery.setParameter(eq("clientId"), any())) + .thenReturn(mockQuery); + when(mockQuery.list()) + .thenReturn(expectedWarehouseIds); + + @SuppressWarnings("unchecked") + List result = (List) getWarehousesMethod.invoke( + reportValuationStock, + CLIENT_ID, + ORG_ID + ); + + assertEquals("Should return correct number of warehouses", + expectedWarehouseIds.size(), result.size()); + assertTrue("Should contain expected warehouse IDs", + result.containsAll(expectedWarehouseIds)); + } + } + + /** + * Tests the {@code getWarehouses} method with valid inputs, expecting an empty list when no results are found. + * + * @throws Exception if the method invocation fails. + */ + @Test + public void testGetWarehousesWithNoResults() throws Exception { + List expectedOrgIds = Arrays.asList("org1", "org2"); + List emptyWarehouseList = List.of(); + + try (MockedStatic obContextMock = mockStatic(OBContext.class); + MockedStatic obDalMock = mockStatic(OBDal.class)) { + + obContextMock.when(OBContext::getOBContext).thenReturn(mockOBContext); + when(mockOBContext.getOrganizationStructureProvider(CLIENT_ID)) + .thenReturn(mockOsp); + when(mockOsp.getNaturalTree(ORG_ID)) + .thenReturn(Set.copyOf(expectedOrgIds)); + + obDalMock.when(OBDal::getReadOnlyInstance).thenReturn(mockOBDal); + when(mockOBDal.getSession()).thenReturn(mockSession); + when(mockSession.createQuery(anyString(), eq(String.class))) + .thenReturn(mockQuery); + when(mockQuery.setParameterList((String) eq("orgIds"), (Collection) any())) + .thenReturn(mockQuery); + when(mockQuery.setParameter(eq("clientId"), any())) + .thenReturn(mockQuery); + when(mockQuery.list()) + .thenReturn(emptyWarehouseList); + + @SuppressWarnings("unchecked") + List result = (List) getWarehousesMethod.invoke( + reportValuationStock, + CLIENT_ID, + ORG_ID + ); + + assertTrue("Should return empty list when no warehouses found", + result.isEmpty()); + } + } +} \ No newline at end of file diff --git a/src-test/src/com/smf/jobs/defaults/CloneOrderHookTest.java b/src-test/src/com/smf/jobs/defaults/CloneOrderHookTest.java new file mode 100644 index 000000000..de57d080b --- /dev/null +++ b/src-test/src/com/smf/jobs/defaults/CloneOrderHookTest.java @@ -0,0 +1,244 @@ +package com.smf.jobs.defaults; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.lang.reflect.Method; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.Session; +import org.hibernate.query.Query; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.junit.MockitoJUnitRunner; +import org.openbravo.base.structure.BaseOBObject; +import org.openbravo.base.weld.WeldUtils; +import org.openbravo.dal.core.DalUtil; +import org.openbravo.dal.core.OBContext; +import org.openbravo.dal.service.OBDal; +import org.openbravo.dal.service.OBQuery; +import org.openbravo.erpCommon.businessUtility.CloneOrderHookCaller; +import org.openbravo.model.ad.access.User; +import org.openbravo.model.ad.system.Client; +import org.openbravo.model.common.enterprise.Organization; +import org.openbravo.model.common.order.Order; +import org.openbravo.model.common.order.OrderLine; +import org.openbravo.model.common.plm.Product; +import org.openbravo.model.pricing.pricelist.PriceList; +import org.openbravo.model.pricing.pricelist.PriceListVersion; +import org.openbravo.service.db.CallStoredProcedure; + +@RunWith(MockitoJUnitRunner.class) +public class CloneOrderHookTest { + + @InjectMocks + private CloneOrderHook cloneOrderHook; + + @Mock + private Order originalOrder; + + @Mock + private Order clonedOrder; + + @Mock + private User currentUser; + + @Mock + private OBDal obDal; + + @Mock + private Session session; + + @Mock + private OBContext obContext; + + @Mock + private OrderLine originalOrderLine; + + @Mock + private Product product; + + @Mock + private PriceList priceList; + + @Mock + private Client client; + + private MockedStatic mockedOBDal; + private MockedStatic mockedOBContext; + private MockedStatic mockedWeldUtils; + private MockedStatic mockedDalUtil; + private MockedStatic mockedCallStoredProcedure; + private Method cloneOrderMethod; + + @Before + public void setUp() throws Exception { + cloneOrderMethod = CloneOrderHook.class.getDeclaredMethod( + "cloneOrder", + User.class, + Order.class, + Order.class + ); + cloneOrderMethod.setAccessible(true); + + mockedOBDal = mockStatic(OBDal.class); + mockedOBContext = mockStatic(OBContext.class); + mockedWeldUtils = mockStatic(WeldUtils.class); + mockedDalUtil = mockStatic(DalUtil.class); + mockedCallStoredProcedure = mockStatic(CallStoredProcedure.class); + + mockedOBDal.when(OBDal::getInstance).thenReturn(obDal); + mockedOBContext.when(OBContext::getOBContext).thenReturn(obContext); + when(obDal.getSession()).thenReturn(session); + } + + @Test + public void testCloneOrder() throws Exception { + // Setup organization + Organization organization = mock(Organization.class); + + // Setup order lines + List originalOrderLines = new ArrayList<>(); + originalOrderLines.add(originalOrderLine); + when(originalOrder.getOrderLineList()).thenReturn(originalOrderLines); + when(clonedOrder.getOrderLineList()).thenReturn(new ArrayList<>()); + + // Setup basic order configuration + when(originalOrder.getPriceList()).thenReturn(priceList); + when(originalOrder.getClient()).thenReturn(client); + when(originalOrder.isSalesTransaction()).thenReturn(true); + when(priceList.getId()).thenReturn("testPriceListId"); + when(client.getId()).thenReturn("testClientId"); + + // Setup order line details + when(originalOrderLine.getProduct()).thenReturn(product); + when(product.getId()).thenReturn("testProductId"); + when(originalOrderLine.getId()).thenReturn("testOrderLineId"); + when(originalOrderLine.getOrderlineServiceRelationList()).thenReturn(new ArrayList<>()); + + // Mock DalUtil copy + OrderLine clonedOrderLine = mock(OrderLine.class); + mockedDalUtil.when(() -> DalUtil.copy(any(OrderLine.class), eq(false))) + .thenReturn(clonedOrderLine); + + // Mock price list version query + OBQuery mockQuery = mock(OBQuery.class); + when(obDal.createQuery(eq(PriceListVersion.class), anyString())).thenReturn(mockQuery); + when(mockQuery.setNamedParameter(anyString(), any())).thenReturn(mockQuery); + when(mockQuery.list()).thenReturn(new ArrayList<>()); + + // Mock stored procedure call + CallStoredProcedure mockStoredProcedure = mock(CallStoredProcedure.class); + when(mockStoredProcedure.call(anyString(), any(), any())).thenReturn(BigDecimal.ONE); + mockedCallStoredProcedure.when(CallStoredProcedure::getInstance).thenReturn(mockStoredProcedure); + + // Mock CloneOrderHookCaller + CloneOrderHookCaller mockCaller = mock(CloneOrderHookCaller.class); + mockedWeldUtils.when(() -> WeldUtils.getInstanceFromStaticBeanManager(CloneOrderHookCaller.class)) + .thenReturn(mockCaller); + doNothing().when(mockCaller).executeHook(any(Order.class)); + + // Execute test + Order result = (Order) cloneOrderMethod.invoke(cloneOrderHook, currentUser, originalOrder, clonedOrder); + + // Verify results + assertNotNull("Cloned order should not be null", result); + + // Verify the basic order properties + verify(clonedOrder).setDocumentAction("CO"); + verify(clonedOrder).setDocumentStatus("DR"); + verify(clonedOrder).setPosted("N"); + verify(clonedOrder).setProcessed(false); + verify(clonedOrder).setDelivered(false); + verify(clonedOrder, times(2)).setSalesTransaction(anyBoolean()); // Allow 2 calls + verify(clonedOrder).setDocumentNo(null); + verify(clonedOrder).setCreatedBy(currentUser); + verify(clonedOrder).setUpdatedBy(currentUser); + verify(clonedOrder).setGrandTotalAmount(BigDecimal.ZERO); + verify(clonedOrder).setSummedLineAmount(BigDecimal.ZERO); + + // Verify DAL operations + verify(obDal).save(clonedOrder); + verify(obDal).flush(); + verify(obDal).refresh(clonedOrder); + + // Verify order line operations + verify(clonedOrderLine).setSalesOrder(clonedOrder); + verify(clonedOrderLine).setReservedQuantity(BigDecimal.ZERO); + verify(clonedOrderLine).setDeliveredQuantity(BigDecimal.ZERO); + verify(clonedOrderLine).setInvoicedQuantity(BigDecimal.ZERO); + } + + @Test + public void testGetLineNetAmt() { + String testOrderId = "test-order-id"; + BigDecimal expectedAmount = new BigDecimal("100.00"); + List amounts = new ArrayList<>(); + amounts.add(expectedAmount); + + @SuppressWarnings("unchecked") + Query mockQuery = mock(Query.class); + when(session.createQuery(anyString(), eq(BigDecimal.class))).thenReturn(mockQuery); + when(mockQuery.setParameter(anyString(), anyString())).thenReturn(mockQuery); + when(mockQuery.list()).thenReturn(amounts); + + BigDecimal result = CloneOrderHook.getLineNetAmt(testOrderId); + + assertEquals("Line net amount should match expected value", expectedAmount, result); + verify(mockQuery).setParameter("orderId", testOrderId); + } + + @Test + public void testShouldCopyChildren() { + boolean result = cloneOrderHook.shouldCopyChildren(true); + assertEquals("Should always return false regardless of input", false, result); + } + + @Test + public void testPreCopy() { + BaseOBObject result = cloneOrderHook.preCopy(originalOrder); + assertEquals("Should return original record without modification", originalOrder, result); + } + + @After + public void tearDown() { + if (mockedOBDal != null) { + mockedOBDal.close(); + System.out.println("mockedOBDal cerrado correctamente."); + } + if (mockedOBContext != null) { + mockedOBContext.close(); + System.out.println("mockedOBContext cerrado correctamente."); + } + if (mockedWeldUtils != null) { + mockedWeldUtils.close(); + System.out.println("mockedWeldUtils cerrado correctamente."); + } + if (mockedDalUtil != null) { + mockedDalUtil.close(); + System.out.println("mockedDalUtil cerrado correctamente."); + } + if (mockedCallStoredProcedure != null) { + mockedCallStoredProcedure.close(); + System.out.println("mockedCallStoredProcedure cerrado correctamente."); + } + } + +} \ No newline at end of file diff --git a/src-test/src/com/smf/jobs/defaults/PostTest.java b/src-test/src/com/smf/jobs/defaults/PostTest.java new file mode 100644 index 000000000..16ae525d1 --- /dev/null +++ b/src-test/src/com/smf/jobs/defaults/PostTest.java @@ -0,0 +1,219 @@ +package com.smf.jobs.defaults; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.apache.commons.lang.mutable.MutableBoolean; +import org.codehaus.jettison.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; +import org.openbravo.base.model.Entity; +import org.openbravo.base.secureApp.VariablesSecureApp; +import org.openbravo.base.structure.BaseOBObject; +import org.openbravo.client.kernel.RequestContext; +import org.openbravo.dal.service.OBDal; +import org.openbravo.erpCommon.ad_actionButton.ActionButtonUtility; +import org.openbravo.erpCommon.utility.OBError; +import org.openbravo.erpCommon.utility.OBMessageUtils; +import org.openbravo.model.ad.system.Client; +import org.openbravo.model.common.enterprise.Organization; +import org.openbravo.service.db.DalConnectionProvider; + +import com.smf.jobs.ActionResult; +import com.smf.jobs.Result; + +@RunWith(MockitoJUnitRunner.class) +public class PostTest { + + @Spy + private Post post; + + @Mock + private OBDal obDal; + + @Mock + private RequestContext requestContext; + @Mock + private VariablesSecureApp vars; + @Mock + private BaseOBObject mockRecord; + @Mock + private Organization organization; + @Mock + private Client client; + @Mock + private Entity entity; + + @Before + public void setUp() { + + when(organization.getId()).thenReturn("testOrgId"); + when(entity.getTableId()).thenReturn("318"); + + when(mockRecord.getId()).thenReturn("testId"); + when(mockRecord.getEntity()).thenReturn(entity); + when(mockRecord.get("organization")).thenReturn(organization); + when(mockRecord.get("client")).thenReturn(client); + + } + + @Test + public void testActionWithMultipleSuccessfulPostings() throws Exception { + JSONObject parameters = new JSONObject(); + MutableBoolean isStopped = new MutableBoolean(false); + + BaseOBObject mockRecord2 = mock(BaseOBObject.class); + when(mockRecord2.getId()).thenReturn("testId2"); + when(mockRecord2.get("posted")).thenReturn("N"); + when(mockRecord2.getEntity()).thenReturn(entity); + when(mockRecord2.get("organization")).thenReturn(organization); + when(mockRecord2.get("client")).thenReturn(client); + + List records = Arrays.asList(mockRecord, mockRecord2); + + OBError successResult = new OBError(); + successResult.setType("Success"); + successResult.setMessage("Posted successfully"); + + try (MockedStatic requestContextMock = mockStatic(RequestContext.class); + MockedStatic actionButtonUtilityMock = mockStatic(ActionButtonUtility.class); + MockedStatic obDalMock = mockStatic(OBDal.class); + MockedStatic messageMock = mockStatic(OBMessageUtils.class)) { + + requestContextMock.when(RequestContext::get).thenReturn(requestContext); + when(requestContext.getVariablesSecureApp()).thenReturn(vars); + obDalMock.when(OBDal::getInstance).thenReturn(obDal); + + actionButtonUtilityMock.when(() -> ActionButtonUtility.processButton( + any(VariablesSecureApp.class), + anyString(), + anyString(), + anyString(), + any(DalConnectionProvider.class) + )).thenReturn(successResult); + + messageMock.when(() -> OBMessageUtils.messageBD(anyString())).thenReturn("DJOBS_PostUnpostMessage"); + doReturn(records).when(post).getInputContents(any()); + + ActionResult result = post.action(parameters, isStopped); + + assertNotNull("Result should not be null", result); + assertEquals("Should return success type", Result.Type.SUCCESS, result.getType()); + verify(mockRecord, times(1)).getId(); + verify(mockRecord2, times(1)).getId(); + } + } + + @Test + public void testActionWithMixedResults() throws Exception { + JSONObject parameters = new JSONObject(); + MutableBoolean isStopped = new MutableBoolean(false); + + BaseOBObject mockRecord2 = mock(BaseOBObject.class); + when(mockRecord2.getId()).thenReturn("testId2"); + when(mockRecord2.get("posted")).thenReturn("N"); + when(mockRecord2.getEntity()).thenReturn(entity); + when(mockRecord2.get("organization")).thenReturn(organization); + when(mockRecord2.get("client")).thenReturn(client); + + List records = Arrays.asList(mockRecord, mockRecord2); + + OBError successResult = new OBError(); + successResult.setType("Success"); + OBError errorResult = new OBError(); + errorResult.setType("Error"); + + try (MockedStatic requestContextMock = mockStatic(RequestContext.class); + MockedStatic actionButtonUtilityMock = mockStatic(ActionButtonUtility.class); + MockedStatic obDalMock = mockStatic(OBDal.class); + MockedStatic messageMock = mockStatic(OBMessageUtils.class)) { + + requestContextMock.when(RequestContext::get).thenReturn(requestContext); + when(requestContext.getVariablesSecureApp()).thenReturn(vars); + obDalMock.when(OBDal::getInstance).thenReturn(obDal); + + actionButtonUtilityMock.when(() -> ActionButtonUtility.processButton( + any(VariablesSecureApp.class), + eq("testId"), + anyString(), + anyString(), + any(DalConnectionProvider.class) + )).thenReturn(successResult); + + actionButtonUtilityMock.when(() -> ActionButtonUtility.processButton( + any(VariablesSecureApp.class), + eq("testId2"), + anyString(), + anyString(), + any(DalConnectionProvider.class) + )).thenReturn(errorResult); + + messageMock.when(() -> OBMessageUtils.messageBD(anyString())).thenReturn("DJOBS_PostUnpostMessage"); + doReturn(records).when(post).getInputContents(any()); + + ActionResult result = post.action(parameters, isStopped); + + assertNotNull("Result should not be null", result); + assertEquals("Should return warning type for mixed results", Result.Type.WARNING, result.getType()); + } + } + + @Test + public void testActionWithEmptyRecordList() throws Exception { + JSONObject parameters = new JSONObject(); + MutableBoolean isStopped = new MutableBoolean(false); + List records = Collections.emptyList(); + + try (MockedStatic requestContextMock = mockStatic(RequestContext.class); + MockedStatic obDalMock = mockStatic(OBDal.class)) { + + requestContextMock.when(RequestContext::get).thenReturn(requestContext); + when(requestContext.getVariablesSecureApp()).thenReturn(vars); + obDalMock.when(OBDal::getInstance).thenReturn(obDal); + + doReturn(records).when(post).getInputContents(any()); + + ActionResult result = post.action(parameters, isStopped); + + assertNotNull("Result should not be null", result); + assertEquals("Should return success type for empty list", Result.Type.SUCCESS, result.getType()); + } + } + + + @Test + public void testActionWithException() throws Exception { + JSONObject parameters = new JSONObject(); + MutableBoolean isStopped = new MutableBoolean(false); + List records = Collections.singletonList(mockRecord); + + try (MockedStatic requestContextMock = mockStatic(RequestContext.class); + MockedStatic obDalMock = mockStatic(OBDal.class)) { + + requestContextMock.when(RequestContext::get).thenReturn(requestContext); + when(requestContext.getVariablesSecureApp()).thenReturn(vars); + obDalMock.when(OBDal::getInstance).thenReturn(obDal); + + doReturn(records).when(post).getInputContents(any()); + doThrow(new RuntimeException("Test exception")).when(mockRecord).get("posted"); + + ActionResult result = post.action(parameters, isStopped); + + assertNotNull("Result should not be null", result); + assertEquals("Should return error type", Result.Type.ERROR, result.getType()); + assertEquals("Should return exception message", "Test exception", result.getMessage()); + } + } +} \ No newline at end of file diff --git a/src-test/src/com/smf/jobs/defaults/ProcessInvoicesTest.java b/src-test/src/com/smf/jobs/defaults/ProcessInvoicesTest.java new file mode 100644 index 000000000..01cb3a7bf --- /dev/null +++ b/src-test/src/com/smf/jobs/defaults/ProcessInvoicesTest.java @@ -0,0 +1,298 @@ +package com.smf.jobs.defaults; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.lang.reflect.Method; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +import org.apache.commons.lang.mutable.MutableBoolean; +import org.codehaus.jettison.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; +import org.openbravo.advpaymentmngt.ProcessInvoiceUtil; +import org.openbravo.base.secureApp.VariablesSecureApp; +import org.openbravo.base.weld.WeldUtils; +import org.openbravo.client.kernel.RequestContext; +import org.openbravo.dal.service.OBDal; +import org.openbravo.erpCommon.utility.OBDateUtils; +import org.openbravo.erpCommon.utility.OBError; +import org.openbravo.model.common.invoice.Invoice; +import org.openbravo.service.db.DalConnectionProvider; +import org.openbravo.service.json.JsonUtils; + +import com.smf.jobs.ActionResult; +import com.smf.jobs.Result; +import com.smf.jobs.Data; + +/** + * Unit tests for the ProcessInvoices class. + * This class contains tests to validate the behavior of processing invoices + * in various scenarios, such as handling void dates, verifying successful + * processing, and ensuring proper pre-run setup. + * + * It uses JUnit and Mockito for testing and mocking dependencies. + */ +@RunWith(MockitoJUnitRunner.class) +public class ProcessInvoicesTest { + + @Spy + @InjectMocks + private TestableProcessInvoices processInvoices; + + @Mock + private WeldUtils mockWeldUtils; + + @Mock + private ProcessInvoiceUtil mockProcessInvoiceUtil; + + @Mock + private RequestContext mockRequestContext; + + @Mock + private VariablesSecureApp mockVars; + + @Mock + private Invoice mockInvoice; + + @Mock + private OBDal mockOBDal; + + @Mock + private Data mockData; + + private Method processInvoiceMethod; + + /** + * Sets up the test environment, including retrieving the private method + * "processInvoice" from the ProcessInvoices class for invocation in tests. + * + * @throws Exception if the method cannot be accessed or found. + */ + @Before + public void setUp() throws Exception { + processInvoiceMethod = ProcessInvoices.class.getDeclaredMethod( + "processInvoice", + Invoice.class, + String.class, + String.class, + String.class + ); + processInvoiceMethod.setAccessible(true); + } + + /** + * Tests the processInvoice method when void dates are not provided. + * Validates that the invoice is processed successfully with the provided + * document action. + * + * @throws Exception if the method invocation fails. + */ + @Test + public void testProcessInvoiceWithoutVoidDates() throws Exception { + String invoiceId = "test-invoice-id"; + String docAction = "CO"; + OBError expectedResult = new OBError(); + expectedResult.setType("Success"); + expectedResult.setMessage("Invoice processed successfully"); + + try (MockedStatic requestContextMock = mockStatic(RequestContext.class)) { + requestContextMock.when(RequestContext::get).thenReturn(mockRequestContext); + when(mockRequestContext.getVariablesSecureApp()).thenReturn(mockVars); + when(mockWeldUtils.getInstance(ProcessInvoiceUtil.class)).thenReturn(mockProcessInvoiceUtil); + when(mockInvoice.getId()).thenReturn(invoiceId); + when(mockProcessInvoiceUtil.process( + eq(invoiceId), + eq(docAction), + eq(""), + eq(""), + any(VariablesSecureApp.class), + any(DalConnectionProvider.class) + )).thenReturn(expectedResult); + + OBError result = (OBError) processInvoiceMethod.invoke( + processInvoices, + mockInvoice, + docAction, + null, + null + ); + + assertEquals("Should return success type", "Success", result.getType()); + assertEquals("Should return correct message", "Invoice processed successfully", result.getMessage()); + } + } + + /** + * Tests the processInvoice method when void dates are provided. + * Validates that the invoice is processed successfully and formatted + * dates are passed to the process method. + * + * @throws Exception if the method invocation fails. + */ + @Test + public void testProcessInvoiceWithVoidDates() throws Exception { + String invoiceId = "test-invoice-id"; + String docAction = "VO"; + String voidDate = "2024-01-15"; + String voidAcctDate = "2024-01-15"; + + OBError expectedResult = new OBError(); + expectedResult.setType("Success"); + + SimpleDateFormat jsonDateFormat = JsonUtils.createDateFormat(); + Date testDate = jsonDateFormat.parse(voidDate); + String formattedDate = OBDateUtils.formatDate(testDate); + + try (MockedStatic requestContextMock = mockStatic(RequestContext.class)) { + requestContextMock.when(RequestContext::get).thenReturn(mockRequestContext); + when(mockRequestContext.getVariablesSecureApp()).thenReturn(mockVars); + when(mockWeldUtils.getInstance(ProcessInvoiceUtil.class)).thenReturn(mockProcessInvoiceUtil); + when(mockInvoice.getId()).thenReturn(invoiceId); + when(mockProcessInvoiceUtil.process( + eq(invoiceId), + eq(docAction), + eq(formattedDate), + eq(formattedDate), + any(VariablesSecureApp.class), + any(DalConnectionProvider.class) + )).thenReturn(expectedResult); + + OBError result = (OBError) processInvoiceMethod.invoke( + processInvoices, + mockInvoice, + docAction, + voidDate, + voidAcctDate + ); + + assertEquals("Should return success type", "Success", result.getType()); + } + } + + /** + * Tests the action method to ensure it correctly handles processing invoices + * when the processing result is successful. + * + * @throws Exception if the action execution fails. + */ + @Test + public void testActionWithSuccessfulProcessing() throws Exception { + JSONObject parameters = new JSONObject(); + parameters.put("DocAction", "CO"); + MutableBoolean isStopped = new MutableBoolean(false); + + List mockInvoices = List.of(mockInvoice); + OBError successResult = new OBError(); + successResult.setType("Success"); + + doReturn(mockInvoices).when(processInvoices).getInputContents(any()); + + try (MockedStatic requestContextMock = mockStatic(RequestContext.class)) { + requestContextMock.when(RequestContext::get).thenReturn(mockRequestContext); + when(mockRequestContext.getVariablesSecureApp()).thenReturn(mockVars); + when(mockWeldUtils.getInstance(ProcessInvoiceUtil.class)).thenReturn(mockProcessInvoiceUtil); + when(mockInvoice.getId()).thenReturn("testId"); + when(mockProcessInvoiceUtil.process( + anyString(), + anyString(), + anyString(), + anyString(), + any(VariablesSecureApp.class), + any(DalConnectionProvider.class) + )).thenReturn(successResult); + + ActionResult result = processInvoices.action(parameters, isStopped); + + assertEquals("Should return success type", Result.Type.SUCCESS, result.getType()); + } + } + + /** + * Tests the preRun method to verify that invoices with the "process now" + * flag are properly locked, updated, and saved before processing. + * + * @throws Exception if the preRun setup or execution fails. + */ + @Test + public void testPreRunWithLockedInvoice() throws Exception { + JSONObject jsonContent = new JSONObject(); + JSONObject params = new JSONObject(); + params.put("DocAction", "CO"); + jsonContent.put("_params", params); + + List mockInvoices = List.of(mockInvoice); + OBError successResult = new OBError(); + successResult.setType("Success"); + + try (MockedStatic obDalMock = mockStatic(OBDal.class); + MockedStatic requestContextMock = mockStatic(RequestContext.class)) { + + obDalMock.when(OBDal::getInstance).thenReturn(mockOBDal); + doNothing().when(mockOBDal).save(any()); + doNothing().when(mockOBDal).flush(); + + doReturn(mockInvoices).when(processInvoices).getInputContents(any()); + doReturn(mockData).when(processInvoices).getInput(); + + when(mockInvoice.isProcessNow()).thenReturn(true); + when(mockInvoice.getId()).thenReturn("testId"); + + requestContextMock.when(RequestContext::get).thenReturn(mockRequestContext); + when(mockRequestContext.getVariablesSecureApp()).thenReturn(mockVars); + when(mockWeldUtils.getInstance(ProcessInvoiceUtil.class)).thenReturn(mockProcessInvoiceUtil); + when(mockProcessInvoiceUtil.process( + anyString(), + eq("XL"), + anyString(), + anyString(), + any(VariablesSecureApp.class), + any(DalConnectionProvider.class) + )).thenReturn(successResult); + + Data result = processInvoices.preRun(jsonContent); + + assertNotNull("Result should not be null", result); + verify(mockInvoice, times(1)).setAPRMProcessinvoice("--"); + verify(mockOBDal, times(1)).save(mockInvoice); + verify(mockOBDal, times(1)).flush(); + } + } + + /** + * A testable subclass of ProcessInvoices that exposes certain protected + * or private methods for testing purposes. + */ + public static class TestableProcessInvoices extends ProcessInvoices { + @Override + public Data getInput() { + return super.getInput(); + } + } + + /** + * Verifies that the getInputClass method returns the correct input class + * for processing invoices. + */ + @Test + public void testGetInputClass() { + assertEquals("Should return Invoice.class", Invoice.class, processInvoices.getInputClass()); + } +} \ No newline at end of file diff --git a/src-test/src/com/smf/jobs/defaults/ProcessOrdersDefaultsTest.java b/src-test/src/com/smf/jobs/defaults/ProcessOrdersDefaultsTest.java new file mode 100644 index 000000000..1d115213e --- /dev/null +++ b/src-test/src/com/smf/jobs/defaults/ProcessOrdersDefaultsTest.java @@ -0,0 +1,201 @@ +package com.smf.jobs.defaults; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.junit.MockitoJUnitRunner; +import org.openbravo.base.secureApp.VariablesSecureApp; +import org.openbravo.client.kernel.RequestContext; +import org.openbravo.data.FieldProvider; +import org.openbravo.erpCommon.ad_actionButton.ActionButtonUtility; +import org.openbravo.service.db.DalConnectionProvider; + +/** + * Unit test class for {@link ProcessOrdersDefaults}. + * This class verifies the behavior of methods in the ProcessOrdersDefaults class. + */ +@RunWith(MockitoJUnitRunner.class) +public class ProcessOrdersDefaultsTest { + + @InjectMocks + private ProcessOrdersDefaults processOrdersDefaults; + + @Mock + private RequestContext mockRequestContext; + + @Mock + private VariablesSecureApp mockVars; + + @Mock + private DalConnectionProvider mockConnectionProvider; + + /** + * Sets up the test environment before each test case. + * Initializes common mocks and variables required across tests. + */ + @Before + public void setUp() { + // Common setup if needed + } + + /** + * Sets up the test environment before each test case. + * Initializes common mocks and variables required across tests. + */ + @Test + public void testExecuteWithSingleDocumentStatus() throws Exception { + Map parameters = new HashMap<>(); + String content = new JSONObject() + .put("documentStatuses", new JSONArray().put("DR")) + .put("isProcessing", "N") + .put("tabId", "123") + .toString(); + + FieldProvider mockFieldProvider = mock(FieldProvider.class); + when(mockFieldProvider.getField("ID")).thenReturn("CO"); + FieldProvider[] mockFields = new FieldProvider[]{mockFieldProvider}; + + try (MockedStatic requestContextMock = mockStatic(RequestContext.class); + MockedStatic actionButtonUtilityMock = mockStatic(ActionButtonUtility.class)) { + + requestContextMock.when(RequestContext::get).thenReturn(mockRequestContext); + when(mockRequestContext.getVariablesSecureApp()).thenReturn(mockVars); + + actionButtonUtilityMock.when(() -> ActionButtonUtility.docAction( + any(), + any(), + anyString(), + eq(ProcessOrdersDefaults.ORDER_DOCUMENT_ACTION_REFERENCE_ID), + eq("DR"), + eq("N"), + eq(ProcessOrdersDefaults.AD_TABLE_ID), + eq("123") + )).thenReturn(mockFields); + + JSONObject result = processOrdersDefaults.execute(parameters, content); + + assertNotNull("Result should not be null", result); + assertTrue("Result should contain actions", result.has("actions")); + JSONArray actions = result.getJSONArray("actions"); + assertEquals("Should have one action", 1, actions.length()); + assertEquals("Should have correct action", "CO", actions.getString(0)); + } + } + + /** + * Tests the {@link ProcessOrdersDefaults#execute(Map, String)} method when there are multiple document statuses. + * Verifies the result structure and correctness of returned actions. + * + * @throws Exception if an error occurs during test execution + */ + @Test + public void testExecuteWithMultipleDocumentStatuses() throws Exception { + Map parameters = new HashMap<>(); + String content = new JSONObject() + .put("documentStatuses", new JSONArray().put("DR").put("CO")) + .put("isProcessing", "N") + .put("tabId", "123") + .toString(); + + FieldProvider mockFieldProvider1 = mock(FieldProvider.class); + FieldProvider mockFieldProvider2 = mock(FieldProvider.class); + when(mockFieldProvider1.getField("ID")).thenReturn("CO"); + when(mockFieldProvider2.getField("ID")).thenReturn("CL"); + + FieldProvider[] mockFields1 = new FieldProvider[]{mockFieldProvider1}; + FieldProvider[] mockFields2 = new FieldProvider[]{mockFieldProvider2}; + + try (MockedStatic requestContextMock = mockStatic(RequestContext.class); + MockedStatic actionButtonUtilityMock = mockStatic(ActionButtonUtility.class)) { + + requestContextMock.when(RequestContext::get).thenReturn(mockRequestContext); + when(mockRequestContext.getVariablesSecureApp()).thenReturn(mockVars); + + actionButtonUtilityMock.when(() -> ActionButtonUtility.docAction( + any(), + any(), + anyString(), + eq(ProcessOrdersDefaults.ORDER_DOCUMENT_ACTION_REFERENCE_ID), + eq("DR"), + eq("N"), + eq(ProcessOrdersDefaults.AD_TABLE_ID), + eq("123") + )).thenReturn(mockFields1); + + actionButtonUtilityMock.when(() -> ActionButtonUtility.docAction( + any(), + any(), + anyString(), + eq(ProcessOrdersDefaults.ORDER_DOCUMENT_ACTION_REFERENCE_ID), + eq("CO"), + eq("N"), + eq(ProcessOrdersDefaults.AD_TABLE_ID), + eq("123") + )).thenReturn(mockFields2); + + JSONObject result = processOrdersDefaults.execute(parameters, content); + + assertNotNull("Result should not be null", result); + assertTrue("Result should contain actions", result.has("actions")); + JSONArray actions = result.getJSONArray("actions"); + assertEquals("Should have two actions", 2, actions.length()); + assertEquals("First action should be CO", "CO", actions.getString(0)); + assertEquals("Second action should be CL", "CL", actions.getString(1)); + } + } + + /** + * Tests the {@link ProcessOrdersDefaults(String, String, String, VariablesSecureApp, DalConnectionProvider)} + * method to ensure it correctly retrieves document actions based on input parameters. + */ + @Test + public void testGetDocumentActionList() { + FieldProvider mockFieldProvider = mock(FieldProvider.class); + when(mockFieldProvider.getField("ID")).thenReturn("CO"); + FieldProvider[] mockFields = new FieldProvider[]{mockFieldProvider}; + + try (MockedStatic actionButtonUtilityMock = mockStatic(ActionButtonUtility.class)) { + actionButtonUtilityMock.when(() -> ActionButtonUtility.docAction( + any(), + any(), + anyString(), + anyString(), + anyString(), + anyString(), + anyString(), + anyString() + )).thenReturn(mockFields); + + List result = ProcessOrdersDefaults.getDocumentActionList( + "DR", + "N", + "123", + mockVars, + mockConnectionProvider + ); + + assertNotNull("Result should not be null", result); + assertEquals("Should have one action", 1, result.size()); + assertEquals("Should have correct action", "CO", result.get(0)); + } + } +} \ No newline at end of file diff --git a/src-test/src/com/smf/jobs/defaults/ProcessOrdersTest.java b/src-test/src/com/smf/jobs/defaults/ProcessOrdersTest.java new file mode 100644 index 000000000..072e1cc22 --- /dev/null +++ b/src-test/src/com/smf/jobs/defaults/ProcessOrdersTest.java @@ -0,0 +1,183 @@ +package com.smf.jobs.defaults; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.doReturn; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; + +import org.apache.commons.lang.mutable.MutableBoolean; +import org.codehaus.jettison.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.MockedStatic; +import org.mockito.junit.MockitoJUnitRunner; +import org.openbravo.advpaymentmngt.ProcessOrderUtil; +import org.openbravo.base.secureApp.VariablesSecureApp; +import org.openbravo.base.weld.WeldUtils; +import org.openbravo.client.kernel.RequestContext; +import org.openbravo.erpCommon.utility.OBError; +import org.openbravo.model.common.order.Order; +import org.openbravo.service.db.DalConnectionProvider; + +import com.smf.jobs.ActionResult; +import com.smf.jobs.Result; + +/** + * Unit tests for the {@code ProcessOrders} class. + * Verifies the functionality for processing orders, including: + * - Reflection-based tests for private methods. + * - Handling of successful and erroneous scenarios during order processing. + */ +@RunWith(MockitoJUnitRunner.class) +public class ProcessOrdersTest { + + @Spy + @InjectMocks + private ProcessOrders processOrders; + + @Mock + private WeldUtils mockWeldUtils; + + @Mock + private ProcessOrderUtil mockOrderUtil; + + @Mock + private RequestContext mockRequestContext; + + @Mock + private VariablesSecureApp mockVars; + + @Mock + private Order mockOrder; + + private Method processOrderMethod; + + /** + * Sets up the test environment, initializing mock dependencies and + * preparing the {@code processOrder} method for reflection-based testing. + * + * @throws Exception If setup fails or reflection setup encounters issues. + */ + @Before + public void setUp() throws Exception { + processOrderMethod = ProcessOrders.class.getDeclaredMethod( + "processOrder", + Order.class, + String.class + ); + processOrderMethod.setAccessible(true); + } + + /** + * Tests the {@code processOrder} private method using reflection to ensure + * an order is successfully processed and the correct result is returned. + * + * @throws Exception If invocation of the private method fails. + */ + @Test + public void testProcessOrder() throws Exception { + String orderId = "test-order-id"; + String docAction = "CO"; + OBError expectedResult = new OBError(); + expectedResult.setType("Success"); + expectedResult.setMessage("Order processed successfully"); + + try (MockedStatic requestContextMock = mockStatic(RequestContext.class)) { + requestContextMock.when(RequestContext::get).thenReturn(mockRequestContext); + when(mockRequestContext.getVariablesSecureApp()).thenReturn(mockVars); + when(mockWeldUtils.getInstance(ProcessOrderUtil.class)).thenReturn(mockOrderUtil); + when(mockOrder.getId()).thenReturn(orderId); + when(mockOrderUtil.process( + eq(orderId), + eq(docAction), + any(VariablesSecureApp.class), + any(DalConnectionProvider.class) + )).thenReturn(expectedResult); + + OBError result = (OBError) processOrderMethod.invoke( + processOrders, + mockOrder, + docAction + ); + + assertEquals("Should return success type", "Success", result.getType()); + assertEquals( + "Should return correct message", + "Order processed successfully", + result.getMessage() + ); + } + } + + /** + * Verifies the successful execution of the {@code action} method when + * valid orders and parameters are provided. + * + * @throws Exception If the processing fails unexpectedly. + */ + @Test + public void testActionWithSuccessfulProcessing() throws Exception { + JSONObject parameters = new JSONObject(); + parameters.put("DocAction", "CO"); + MutableBoolean isStopped = new MutableBoolean(false); + + List mockOrders = Arrays.asList(mockOrder); + OBError successResult = new OBError(); + successResult.setType("Success"); + + doReturn(mockOrders).when(processOrders).getInputContents(any()); + + try (MockedStatic requestContextMock = mockStatic(RequestContext.class)) { + requestContextMock.when(RequestContext::get).thenReturn(mockRequestContext); + when(mockRequestContext.getVariablesSecureApp()).thenReturn(mockVars); + when(mockWeldUtils.getInstance(ProcessOrderUtil.class)).thenReturn(mockOrderUtil); + when(mockOrder.getId()).thenReturn("testId"); + when(mockOrderUtil.process( + anyString(), + anyString(), + any(VariablesSecureApp.class), + any(DalConnectionProvider.class) + )).thenReturn(successResult); + + ActionResult result = processOrders.action(parameters, isStopped); + + assertEquals("Should return success type", Result.Type.SUCCESS, result.getType()); + } + } + + /** + * Tests the {@code action} method to ensure it correctly handles a scenario + * where no valid input orders are provided, returning an error result. + */ + @Test + public void testActionWithError() { + JSONObject parameters = new JSONObject(); + MutableBoolean isStopped = new MutableBoolean(false); + + doReturn(List.of()).when(processOrders).getInputContents(any()); + + ActionResult result = processOrders.action(parameters, isStopped); + + assertEquals("Should return error type", Result.Type.ERROR, result.getType()); + } + + /** + * Validates the correct input class type returned by the {@code getInputClass} method. + * Ensures it matches the expected {@code Order.class} type. + */ + @Test + public void testGetInputClass() { + assertEquals("Should return Order.class", Order.class, processOrders.getInputClass()); + } +} \ No newline at end of file diff --git a/src-test/src/com/smf/jobs/defaults/ProcessShipmentTest.java b/src-test/src/com/smf/jobs/defaults/ProcessShipmentTest.java new file mode 100644 index 000000000..b5873119e --- /dev/null +++ b/src-test/src/com/smf/jobs/defaults/ProcessShipmentTest.java @@ -0,0 +1,406 @@ +package com.smf.jobs.defaults; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.apache.commons.lang.mutable.MutableBoolean; +import org.codehaus.jettison.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; +import org.openbravo.advpaymentmngt.ProcessShipmentUtil; +import org.openbravo.base.secureApp.VariablesSecureApp; +import org.openbravo.base.weld.WeldUtils; +import org.openbravo.client.kernel.RequestContext; +import org.openbravo.erpCommon.utility.OBError; +import org.openbravo.erpCommon.utility.OBMessageUtils; +import org.openbravo.model.materialmgmt.transaction.ShipmentInOut; +import org.openbravo.service.db.DalConnectionProvider; + +import com.smf.jobs.ActionResult; +import com.smf.jobs.Data; +import com.smf.jobs.Result; + +/** + * Unit tests for the {@code ProcessShipment} class. + * Tests functionality related to shipment processing, covering: + * - Private methods using reflection. + * - Actions with successful and error outcomes. + * - Handling of invalid or edge-case inputs. + */ +@RunWith(MockitoJUnitRunner.Silent.class) +public class ProcessShipmentTest { + + /** + * A testable subclass of {@code ProcessShipment} that exposes methods for testing. + */ + public static class TestableProcessShipment extends ProcessShipment { + + /** + * Overrides the {@code getInput} method to expose it for testing. + * @return Data object representing the input for shipment processing. + */ + @Override + public Data getInput() { + return super.getInput(); + } + } + + @Spy + @InjectMocks + private TestableProcessShipment processShipment; + + @Mock + private WeldUtils mockWeldUtils; + + @Mock + private ProcessShipmentUtil mockProcessShipmentUtil; + + @Mock + private RequestContext mockRequestContext; + + @Mock + private VariablesSecureApp mockVars; + + @Mock + private ShipmentInOut mockShipment; + + @Mock + private Data mockData; + + private Method processShipmentMethod; + + /** + * Initializes test dependencies and configurations, such as static mocks + * for utility methods and reflection access to private methods. + * @throws Exception If setup fails. + */ + @Before + public void setUp() throws Exception { + processShipmentMethod = ProcessShipment.class.getDeclaredMethod( + "processShipment", + ShipmentInOut.class, + String.class + ); + processShipmentMethod.setAccessible(true); + + try (MockedStatic messageMock = mockStatic(OBMessageUtils.class)) { + messageMock.when(() -> OBMessageUtils.messageBD(anyString())) + .thenReturn("Test message"); + messageMock.when(() -> OBMessageUtils.parseTranslation(anyString(), any())) + .thenReturn("Test message"); + } + + } + + /** + * Tests the {@code processShipment} private method to ensure it processes + * a shipment with valid data and returns a successful result. + * @throws Exception If invocation of the private method fails. + */ + @Test + public void testProcessShipmentPrivateMethod() throws Exception { + String shipmentId = "test-shipment-id"; + String docAction = "CO"; + OBError expectedResult = new OBError(); + expectedResult.setType("Success"); + expectedResult.setMessage("Shipment processed successfully"); + + try (MockedStatic requestContextMock = mockStatic(RequestContext.class)) { + requestContextMock.when(RequestContext::get).thenReturn(mockRequestContext); + when(mockRequestContext.getVariablesSecureApp()).thenReturn(mockVars); + when(mockWeldUtils.getInstance(ProcessShipmentUtil.class)).thenReturn(mockProcessShipmentUtil); + when(mockShipment.getId()).thenReturn(shipmentId); + when(mockProcessShipmentUtil.process( + eq(shipmentId), + eq(docAction), + any(VariablesSecureApp.class), + any(DalConnectionProvider.class) + )).thenReturn(expectedResult); + + OBError result = (OBError) processShipmentMethod.invoke( + processShipment, + mockShipment, + docAction + ); + + assertNotNull("Result should not be null", result); + assertEquals("Should return success type", "Success", result.getType()); + assertEquals( + "Should return correct message", + "Shipment processed successfully", + result.getMessage() + ); + } + } + + /** + * Verifies the successful execution of the {@code action} method when + * valid shipments and parameters are provided. + * @throws Exception If processing fails unexpectedly. + */ + @Test + public void testActionWithSuccessfulProcessing() throws Exception { + JSONObject parameters = new JSONObject(); + parameters.put("DocAction", "CO"); + MutableBoolean isStopped = new MutableBoolean(false); + + List mockShipments = List.of(mockShipment); + OBError successResult = new OBError(); + successResult.setType("Success"); + successResult.setMessage("Shipment processed successfully"); + + try (MockedStatic requestContextMock = mockStatic(RequestContext.class)) { + requestContextMock.when(RequestContext::get).thenReturn(mockRequestContext); + when(mockRequestContext.getVariablesSecureApp()).thenReturn(mockVars); + when(mockWeldUtils.getInstance(ProcessShipmentUtil.class)).thenReturn(mockProcessShipmentUtil); + when(mockShipment.getId()).thenReturn("testId"); + when(mockProcessShipmentUtil.process( + anyString(), + anyString(), + any(VariablesSecureApp.class), + any(DalConnectionProvider.class) + )).thenReturn(successResult); + + doReturn(mockShipments).when(processShipment).getInputContents(any()); + doReturn(mockData).when(processShipment).getInput(); + + ActionResult result = processShipment.action(parameters, isStopped); + + assertNotNull("Result should not be null", result); + assertEquals("Should return success type", Result.Type.SUCCESS, result.getType()); + verify(mockProcessShipmentUtil, times(1)).process( + anyString(), + anyString(), + any(VariablesSecureApp.class), + any(DalConnectionProvider.class) + ); + } + } + + /** + * Tests the {@code action} method to ensure it handles errors appropriately + * when an unexpected condition occurs during shipment processing. + */ + @Test + public void testActionWithError() { + JSONObject parameters = new JSONObject(); + MutableBoolean isStopped = new MutableBoolean(false); + + List mockShipments = List.of(mockShipment); + + doReturn(mockShipments).when(processShipment).getInputContents(any()); + + ActionResult result = processShipment.action(parameters, isStopped); + + assertEquals("Should return error type", Result.Type.ERROR, result.getType()); + } + + /** + * Checks that the {@code action} method can handle cases where input is empty, + * returning a successful result without performing any actions. + * @throws Exception If processing fails. + */ + @Test + public void testActionWithEmptyInput() throws Exception { + JSONObject parameters = new JSONObject(); + parameters.put("DocAction", "CO"); + MutableBoolean isStopped = new MutableBoolean(false); + + List emptyShipments = Collections.emptyList(); + doReturn(emptyShipments).when(processShipment).getInputContents(any()); + doReturn(mockData).when(processShipment).getInput(); + + ActionResult result = processShipment.action(parameters, isStopped); + + assertNotNull("Result should not be null", result); + assertEquals("Should return success type for empty input", Result.Type.SUCCESS, result.getType()); + } + + /** + * Tests the {@code processShipment} private method to ensure it processes + * a valid shipment and returns an OBError with the expected success result. + * Validates that the returned OBError contains the correct type and message. + * + * @throws Exception If invocation of the private method fails or an unexpected exception occurs. + */ + @Test + public void testProcessShipment() throws Exception { + String shipmentId = "test-shipment-id"; + String docAction = "CO"; + OBError expectedResult = new OBError(); + expectedResult.setType("Success"); + expectedResult.setMessage("Shipment processed successfully"); + + try (MockedStatic requestContextMock = mockStatic(RequestContext.class)) { + requestContextMock.when(RequestContext::get).thenReturn(mockRequestContext); + when(mockRequestContext.getVariablesSecureApp()).thenReturn(mockVars); + when(mockWeldUtils.getInstance(ProcessShipmentUtil.class)).thenReturn(mockProcessShipmentUtil); + when(mockShipment.getId()).thenReturn(shipmentId); + when(mockProcessShipmentUtil.process( + eq(shipmentId), + eq(docAction), + any(VariablesSecureApp.class), + any(DalConnectionProvider.class) + )).thenReturn(expectedResult); + + OBError result = (OBError) processShipmentMethod.invoke( + processShipment, + mockShipment, + docAction + ); + + assertNotNull("Result should not be null", result); + assertEquals("Should return success type", "Success", result.getType()); + } + } + + /** + * Validates the {@code processShipment} private method when the input shipment is null, + * ensuring a {@code NullPointerException} is thrown as expected. + * @throws Exception If invocation fails. + */ + @Test + public void testProcessShipmentWithNullShipment() throws Exception { + try (MockedStatic requestContextMock = mockStatic(RequestContext.class)) { + requestContextMock.when(RequestContext::get).thenReturn(mockRequestContext); + when(mockRequestContext.getVariablesSecureApp()).thenReturn(mockVars); + + try { + processShipmentMethod.invoke(processShipment, null, "CO"); + fail("Should throw NullPointerException"); + } catch (InvocationTargetException e) { + assertTrue(e.getCause() instanceof NullPointerException); + } + } + } + + /** + * Ensures the {@code action} method identifies and handles invalid document actions, + * returning an appropriate error result. + * @throws Exception If an unexpected exception occurs. + */ + @Test + public void testActionWithInvalidDocAction() throws Exception { + JSONObject parameters = new JSONObject(); + parameters.put("DocAction", "INVALID_ACTION"); + MutableBoolean isStopped = new MutableBoolean(false); + + List mockShipments = List.of(mockShipment); + OBError errorResult = new OBError(); + errorResult.setType("Error"); + errorResult.setMessage("Invalid document action"); + + try (MockedStatic requestContextMock = mockStatic(RequestContext.class); + MockedStatic messageMock = mockStatic(OBMessageUtils.class)) { + + requestContextMock.when(RequestContext::get).thenReturn(mockRequestContext); + when(mockRequestContext.getVariablesSecureApp()).thenReturn(mockVars); + when(mockWeldUtils.getInstance(ProcessShipmentUtil.class)).thenReturn(mockProcessShipmentUtil); + when(mockShipment.getId()).thenReturn("testId"); + when(mockProcessShipmentUtil.process( + anyString(), + eq("INVALID_ACTION"), + any(VariablesSecureApp.class), + any(DalConnectionProvider.class) + )).thenReturn(errorResult); + + messageMock.when(() -> OBMessageUtils.messageBD(anyString())) + .thenReturn("Test message"); + + doReturn(mockShipments).when(processShipment).getInputContents(any()); + doReturn(mockData).when(processShipment).getInput(); + + ActionResult result = processShipment.action(parameters, isStopped); + + assertEquals("Should return error type for invalid action", Result.Type.ERROR, result.getType()); + } + } + + /** + * Tests processing of multiple shipments through the {@code action} method, + * ensuring all shipments are processed individually and successfully. + * @throws Exception If processing fails unexpectedly. + */ + @Test + public void testActionWithMultipleShipments() throws Exception { + JSONObject parameters = new JSONObject(); + parameters.put("DocAction", "CO"); + MutableBoolean isStopped = new MutableBoolean(false); + + ShipmentInOut mockShipment2 = mock(ShipmentInOut.class); + ShipmentInOut mockShipment3 = mock(ShipmentInOut.class); + List multipleShipments = Arrays.asList(mockShipment, mockShipment2, mockShipment3); + + OBError successResult = new OBError(); + successResult.setType("Success"); + + try (MockedStatic requestContextMock = mockStatic(RequestContext.class); + MockedStatic messageMock = mockStatic(OBMessageUtils.class)) { + + requestContextMock.when(RequestContext::get).thenReturn(mockRequestContext); + when(mockRequestContext.getVariablesSecureApp()).thenReturn(mockVars); + when(mockWeldUtils.getInstance(ProcessShipmentUtil.class)).thenReturn(mockProcessShipmentUtil); + + when(mockShipment.getId()).thenReturn("testId1"); + when(mockShipment2.getId()).thenReturn("testId2"); + when(mockShipment3.getId()).thenReturn("testId3"); + + when(mockProcessShipmentUtil.process( + anyString(), + anyString(), + any(VariablesSecureApp.class), + any(DalConnectionProvider.class) + )).thenReturn(successResult); + + messageMock.when(() -> OBMessageUtils.messageBD(anyString())) + .thenReturn("Test message"); + + doReturn(multipleShipments).when(processShipment).getInputContents(any()); + doReturn(mockData).when(processShipment).getInput(); + + ActionResult result = processShipment.action(parameters, isStopped); + + assertNotNull("Result should not be null", result); + assertEquals("Should return success type", Result.Type.SUCCESS, result.getType()); + verify(mockProcessShipmentUtil, times(3)).process( + anyString(), + anyString(), + any(VariablesSecureApp.class), + any(DalConnectionProvider.class) + ); + } + } + + /** + * Verifies the correct input class type is returned by the {@code getInputClass} method. + */ + @Test + public void testGetInputClass() { + assertEquals("Should return ShipmentInOut.class", ShipmentInOut.class, processShipment.getInputClass()); + } + + +} \ No newline at end of file diff --git a/src-test/src/com/smf/jobs/defaults/invoices/CreateFromOrderTest.java b/src-test/src/com/smf/jobs/defaults/invoices/CreateFromOrderTest.java new file mode 100644 index 000000000..f7fdbc2d4 --- /dev/null +++ b/src-test/src/com/smf/jobs/defaults/invoices/CreateFromOrderTest.java @@ -0,0 +1,47 @@ +package com.smf.jobs.defaults.invoices; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.apache.commons.lang.mutable.MutableBoolean; +import org.codehaus.jettison.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; +import org.openbravo.model.common.order.Order; + +import com.smf.jobs.ActionResult; +import com.smf.jobs.Result; + +@RunWith(MockitoJUnitRunner.class) +public class CreateFromOrderTest { + + @Spy + @InjectMocks + private CreateFromOrder createFromOrder; + + + @Before + public void setUp() { + } + + @Test + public void testActionWithRefreshButton() throws Exception { + JSONObject parameters = new JSONObject(); + parameters.put("_buttonValue", "REFRESH"); + MutableBoolean isStopped = new MutableBoolean(false); + + ActionResult result = createFromOrder.action(parameters, isStopped); + + assertNotNull("Result should not be null", result); + assertEquals("Should return success type", Result.Type.SUCCESS, result.getType()); + } + + @Test + public void testGetInputClass() { + assertEquals("Should return Order.class", Order.class, createFromOrder.getInputClass()); + } +} diff --git a/src-test/src/com/smf/jobs/defaults/invoices/CreateFromOrdersHQLTransformerTest.java b/src-test/src/com/smf/jobs/defaults/invoices/CreateFromOrdersHQLTransformerTest.java new file mode 100644 index 000000000..421b055bc --- /dev/null +++ b/src-test/src/com/smf/jobs/defaults/invoices/CreateFromOrdersHQLTransformerTest.java @@ -0,0 +1,102 @@ +package com.smf.jobs.defaults.invoices; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class CreateFromOrdersHQLTransformerTest { + + private CreateFromOrdersHQLTransformer transformer; + private String baseHqlQuery; + + @BeforeEach + void setUp() { + transformer = new CreateFromOrdersHQLTransformer(); + baseHqlQuery = "SELECT * FROM Orders WHERE includeTax = @linesIncludeTaxes@"; + } + + @Test + void testTransformHqlQueryWhenLinesIncludeTaxesIsTrue() { + Map requestParameters = new HashMap<>(); + requestParameters.put("linesIncludeTaxes", "true"); + Map queryNamedParameters = new HashMap<>(); + + String result = transformer.transformHqlQuery(baseHqlQuery, requestParameters, queryNamedParameters); + + assertEquals("SELECT * FROM Orders WHERE includeTax = 'Y'", result); + } + + @Test + void testTransformHqlQueryWhenLinesIncludeTaxesIsFalse() { + Map requestParameters = new HashMap<>(); + requestParameters.put("linesIncludeTaxes", "false"); + Map queryNamedParameters = new HashMap<>(); + + String result = transformer.transformHqlQuery(baseHqlQuery, requestParameters, queryNamedParameters); + + assertEquals("SELECT * FROM Orders WHERE includeTax = 'N'", result); + } + + @Test + void testTransformHqlQueryWhenLinesIncludeTaxesParameterIsMissing() { + Map requestParameters = new HashMap<>(); + Map queryNamedParameters = new HashMap<>(); + + String result = transformer.transformHqlQuery(baseHqlQuery, requestParameters, queryNamedParameters); + + assertEquals("SELECT * FROM Orders WHERE includeTax = 'N'", result); + } + + @Test + void testTransformHqlQueryWithMultipleReplacements() { + String queryWithMultipleReplacements = + "SELECT * FROM Orders WHERE includeTax = @linesIncludeTaxes@ AND otherField = @linesIncludeTaxes@"; + Map requestParameters = new HashMap<>(); + requestParameters.put("linesIncludeTaxes", "true"); + Map queryNamedParameters = new HashMap<>(); + + String result = transformer.transformHqlQuery(queryWithMultipleReplacements, requestParameters, queryNamedParameters); + + assertEquals("SELECT * FROM Orders WHERE includeTax = 'Y' AND otherField = 'Y'", result); + } + + @Test + void testTransformHqlQueryWithInvalidBooleanValue() { + Map requestParameters = new HashMap<>(); + requestParameters.put("linesIncludeTaxes", "invalid_boolean"); + Map queryNamedParameters = new HashMap<>(); + + String result = transformer.transformHqlQuery(baseHqlQuery, requestParameters, queryNamedParameters); + + assertEquals("SELECT * FROM Orders WHERE includeTax = 'N'", result); + } + + @Test + void testTransformHqlQueryWithEmptyQuery() { + Map requestParameters = new HashMap<>(); + requestParameters.put("linesIncludeTaxes", "true"); + Map queryNamedParameters = new HashMap<>(); + + String result = transformer.transformHqlQuery("", requestParameters, queryNamedParameters); + + assertEquals("", result); + } + + @Test + void testTransformHqlQueryWithNullQuery() { + Map requestParameters = new HashMap<>(); + requestParameters.put("linesIncludeTaxes", "true"); + Map queryNamedParameters = new HashMap<>(); + + assertThrows(NullPointerException.class, () -> { + transformer.transformHqlQuery(null, requestParameters, queryNamedParameters); + }); + } +} \ No newline at end of file diff --git a/src-test/src/com/smf/jobs/defaults/offerPick/OfferAddOrgTest.java b/src-test/src/com/smf/jobs/defaults/offerPick/OfferAddOrgTest.java new file mode 100644 index 000000000..49bb36b37 --- /dev/null +++ b/src-test/src/com/smf/jobs/defaults/offerPick/OfferAddOrgTest.java @@ -0,0 +1,142 @@ +package com.smf.jobs.defaults.offerPick; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assertions.*; + +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.junit.jupiter.MockitoExtension; +import org.openbravo.base.provider.OBProvider; +import org.openbravo.dal.service.OBDal; +import org.openbravo.model.ad.system.Client; +import org.openbravo.model.common.enterprise.Organization; +import org.openbravo.model.pricing.priceadjustment.OrganizationFilter; +import org.openbravo.model.pricing.priceadjustment.PriceAdjustment; +import org.hibernate.Session; + +@ExtendWith(MockitoExtension.class) +public class OfferAddOrgTest { + + @Mock + private OBDal obDal; + + @Mock + private PriceAdjustment priceAdjustment; + + @Mock + private Client client; + + @Mock + private Organization organization; + + @Mock + private Session session; + + private OfferAddOrg offerAddOrg; + + @BeforeEach + public void setup() { + offerAddOrg = new OfferAddOrg(); + } + + @Test + public void testDoPickAndExecuteSingleOrganization() throws JSONException { + try (MockedStatic mockedOBDal = mockStatic(OBDal.class); + MockedStatic mockedOBProvider = mockStatic(OBProvider.class)) { + + // Arrange + mockedOBDal.when(OBDal::getInstance).thenReturn(obDal); + when(obDal.getSession()).thenReturn(session); + when(priceAdjustment.getClient()).thenReturn(client); + + JSONArray selectedLines = new JSONArray(); + JSONObject orgJson = new JSONObject(); + orgJson.put("id", "testId"); + selectedLines.put(orgJson); + + when(obDal.getProxy(eq(Organization.ENTITY_NAME), eq("testId"))).thenReturn(organization); + + OBProvider obProvider = mock(OBProvider.class); + OrganizationFilter mockOrgFilter = mock(OrganizationFilter.class); + + mockedOBProvider.when(OBProvider::getInstance).thenReturn(obProvider); + when(obProvider.get(OrganizationFilter.class)).thenReturn(mockOrgFilter); + + // Act + offerAddOrg.doPickAndExecute(priceAdjustment, selectedLines); + + // Assert + verify(mockOrgFilter).setActive(true); + verify(mockOrgFilter).setClient(client); + verify(mockOrgFilter).setOrganization(organization); + verify(mockOrgFilter).setPriceAdjustment(priceAdjustment); + verify(obDal).save(mockOrgFilter); + } + } + + @Test + public void testDoPickAndExecuteMultipleOrganizations() throws JSONException { + try (MockedStatic mockedOBDal = mockStatic(OBDal.class); + MockedStatic mockedOBProvider = mockStatic(OBProvider.class)) { + + // Arrange + mockedOBDal.when(OBDal::getInstance).thenReturn(obDal); + when(obDal.getSession()).thenReturn(session); + when(priceAdjustment.getClient()).thenReturn(client); + + JSONArray selectedLines = new JSONArray(); + for (int i = 0; i < 150; i++) { + JSONObject orgJson = new JSONObject(); + orgJson.put("id", "testId" + i); + selectedLines.put(orgJson); + } + + when(obDal.getProxy(eq(Organization.ENTITY_NAME), anyString())).thenReturn(organization); + + OBProvider obProvider = mock(OBProvider.class); + OrganizationFilter mockOrgFilter = mock(OrganizationFilter.class); + + mockedOBProvider.when(OBProvider::getInstance).thenReturn(obProvider); + when(obProvider.get(OrganizationFilter.class)).thenReturn(mockOrgFilter); + + // Act + offerAddOrg.doPickAndExecute(priceAdjustment, selectedLines); + + // Assert + verify(obDal, times(150)).save(any()); + verify(obDal, times(2)).flush(); + verify(session, times(2)).clear(); + } + } + + @Test + public void testDoPickAndExecuteInvalidJSON() throws JSONException { + try (MockedStatic mockedOBDal = mockStatic(OBDal.class)) { + // Arrange + mockedOBDal.when(OBDal::getInstance).thenReturn(obDal); + + JSONArray selectedLines = new JSONArray(); + JSONObject invalidJson = new JSONObject(); + invalidJson.put("invalid", "value"); + selectedLines.put(invalidJson); + + + // Act & Assert + assertThrows(JSONException.class, () -> + offerAddOrg.doPickAndExecute(priceAdjustment, selectedLines)); + } + } + + @Test + public void testGetJSONName() { + assertEquals("Conforgprocess", offerAddOrg.getJSONName()); + } +} \ No newline at end of file diff --git a/src-test/src/com/smf/jobs/defaults/offerPick/OfferAddProductCategoryTest.java b/src-test/src/com/smf/jobs/defaults/offerPick/OfferAddProductCategoryTest.java new file mode 100644 index 000000000..cae158382 --- /dev/null +++ b/src-test/src/com/smf/jobs/defaults/offerPick/OfferAddProductCategoryTest.java @@ -0,0 +1,126 @@ +package com.smf.jobs.defaults.offerPick; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.junit.jupiter.MockitoExtension; +import org.openbravo.base.provider.OBProvider; +import org.openbravo.dal.service.OBDal; +import org.openbravo.model.ad.system.Client; +import org.openbravo.model.common.enterprise.Organization; +import org.openbravo.model.common.plm.ProductCategory; +import org.openbravo.model.pricing.priceadjustment.PriceAdjustment; +import org.hibernate.Session; + +@ExtendWith(MockitoExtension.class) +public class OfferAddProductCategoryTest { + + @Mock + private OBDal obDal; + + @Mock + private PriceAdjustment priceAdjustment; + + @Mock + private Client client; + + @Mock + private Organization organization; + + @Mock + private Session session; + + private OfferAddProductCategory offerAddProductCategory; + + @BeforeEach + public void setup() { + offerAddProductCategory = new OfferAddProductCategory(); + when(priceAdjustment.getClient()).thenReturn(client); + when(priceAdjustment.getOrganization()).thenReturn(organization); + } + + @Test + public void testDoPickAndExecuteSingleProductCategory() throws JSONException { + try (MockedStatic mockedOBDal = mockStatic(OBDal.class); + MockedStatic mockedOBProvider = mockStatic(OBProvider.class)) { + + // Arrange + mockedOBDal.when(OBDal::getInstance).thenReturn(obDal); + when(obDal.getSession()).thenReturn(session); + + JSONArray selectedLines = new JSONArray(); + JSONObject productCatJson = new JSONObject(); + productCatJson.put("id", "testId"); + selectedLines.put(productCatJson); + + ProductCategory productCategory = mock(ProductCategory.class); + when(obDal.getProxy(eq(ProductCategory.ENTITY_NAME), eq("testId"))).thenReturn(productCategory); + + OBProvider obProvider = mock(OBProvider.class); + org.openbravo.model.pricing.priceadjustment.ProductCategory mockProductCategory = + mock(org.openbravo.model.pricing.priceadjustment.ProductCategory.class); + + mockedOBProvider.when(OBProvider::getInstance).thenReturn(obProvider); + when(obProvider.get(org.openbravo.model.pricing.priceadjustment.ProductCategory.class)) + .thenReturn(mockProductCategory); + + // Act + offerAddProductCategory.doPickAndExecute(priceAdjustment, selectedLines); + + // Assert + verify(mockProductCategory).setActive(true); + verify(mockProductCategory).setClient(client); + verify(mockProductCategory).setOrganization(organization); + verify(mockProductCategory).setPriceAdjustment(priceAdjustment); + verify(mockProductCategory).setProductCategory(productCategory); + verify(obDal).save(mockProductCategory); + } + } + + @Test + public void testDoPickAndExecuteMultipleProductCategories() throws JSONException { + try (MockedStatic mockedOBDal = mockStatic(OBDal.class); + MockedStatic mockedOBProvider = mockStatic(OBProvider.class)) { + + // Arrange + mockedOBDal.when(OBDal::getInstance).thenReturn(obDal); + when(obDal.getSession()).thenReturn(session); + + JSONArray selectedLines = new JSONArray(); + for (int i = 0; i < 150; i++) { + JSONObject productCatJson = new JSONObject(); + productCatJson.put("id", "testId" + i); + selectedLines.put(productCatJson); + } + + ProductCategory productCategory = mock(ProductCategory.class); + when(obDal.getProxy(eq(ProductCategory.ENTITY_NAME), anyString())).thenReturn(productCategory); + + OBProvider obProvider = mock(OBProvider.class); + org.openbravo.model.pricing.priceadjustment.ProductCategory mockProductCategory = + mock(org.openbravo.model.pricing.priceadjustment.ProductCategory.class); + + mockedOBProvider.when(OBProvider::getInstance).thenReturn(obProvider); + when(obProvider.get(org.openbravo.model.pricing.priceadjustment.ProductCategory.class)) + .thenReturn(mockProductCategory); + + // Act + offerAddProductCategory.doPickAndExecute(priceAdjustment, selectedLines); + + // Assert + verify(obDal, times(150)).save(any()); + verify(obDal, times(2)).flush(); + verify(session, times(2)).clear(); + } + } +} \ No newline at end of file diff --git a/src-test/src/com/smf/jobs/defaults/offerPick/OfferAddProductTest.java b/src-test/src/com/smf/jobs/defaults/offerPick/OfferAddProductTest.java new file mode 100644 index 000000000..7e222f5ee --- /dev/null +++ b/src-test/src/com/smf/jobs/defaults/offerPick/OfferAddProductTest.java @@ -0,0 +1,183 @@ +package com.smf.jobs.defaults.offerPick; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; +import org.hibernate.Session; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.junit.MockitoJUnitRunner; +import org.openbravo.base.provider.OBProvider; +import org.openbravo.dal.service.OBDal; +import org.openbravo.model.ad.system.Client; +import org.openbravo.model.common.enterprise.Organization; +import org.openbravo.model.common.plm.Product; +import org.openbravo.model.pricing.priceadjustment.PriceAdjustment; + +/** + * Unit tests for the {@link OfferAddProduct} class. + * This test class validates the functionality of the OfferAddProduct class + * by testing its behavior in scenarios such as adding a product to an offer, + * processing multiple products, handling invalid JSON, and retrieving its JSON name. + * It uses Mockito for mocking dependencies and ensures the methods work as intended. + */ +@RunWith(MockitoJUnitRunner.class) +public class OfferAddProductTest { + + private OfferAddProduct offerAddProduct; + + @Mock + private OBDal obDal; + + @Mock + private Product product; + + @Mock + private PriceAdjustment priceAdjustment; + + @Mock + private Client client; + + @Mock + private Organization organization; + + @Mock + private org.openbravo.model.pricing.priceadjustment.Product priceAdjustmentProduct; + + @Mock + private Session session; + + /** + * Sets up the required mock objects and default behavior + * before executing each test. + */ + @Before + public void setUp() { + offerAddProduct = new OfferAddProduct(); + + when(priceAdjustment.getClient()).thenReturn(client); + when(priceAdjustment.getOrganization()).thenReturn(organization); + when(obDal.getSession()).thenReturn(session); + } + + /** + * Tests the doPickAndExecute method for the basic scenario where a single product + * is added to an offer. It validates that all operations are called as expected. + * + * @throws Exception if there is any issue during JSON processing or mock interaction + */ + @Test + public void testDoPickAndExecute() throws Exception { + JSONArray selectedLines = new JSONArray(); + JSONObject productJson = new JSONObject(); + productJson.put("id", "test-product-id"); + selectedLines.put(productJson); + + try (MockedStatic obDalStatic = mockStatic(OBDal.class); + MockedStatic obProviderStatic = mockStatic(OBProvider.class)) { + + obDalStatic.when(OBDal::getInstance).thenReturn(obDal); + when(obDal.getProxy(eq(Product.ENTITY_NAME), anyString())).thenReturn(product); + + OBProvider obProvider = mock(OBProvider.class); + obProviderStatic.when(OBProvider::getInstance).thenReturn(obProvider); + when(obProvider.get(org.openbravo.model.pricing.priceadjustment.Product.class)) + .thenReturn(priceAdjustmentProduct); + + doNothing().when(priceAdjustmentProduct).setActive(anyBoolean()); + doNothing().when(priceAdjustmentProduct).setClient(any(Client.class)); + doNothing().when(priceAdjustmentProduct).setOrganization(any(Organization.class)); + doNothing().when(priceAdjustmentProduct).setPriceAdjustment(any(PriceAdjustment.class)); + doNothing().when(priceAdjustmentProduct).setProduct(any(Product.class)); + doNothing().when(obDal).save(any()); + doNothing().when(obDal).flush(); + doNothing().when(session).clear(); + + offerAddProduct.doPickAndExecute(priceAdjustment, selectedLines); + + verify(priceAdjustmentProduct).setActive(true); + verify(priceAdjustmentProduct).setClient(client); + verify(priceAdjustmentProduct).setOrganization(organization); + verify(priceAdjustmentProduct).setPriceAdjustment(priceAdjustment); + verify(priceAdjustmentProduct).setProduct(product); + verify(obDal).save(priceAdjustmentProduct); + } + } + + /** + * Tests the getJSONName method to ensure it returns the correct JSON name. + */ + @Test + public void testGetJSONName() { + assert "Confprodprocess".equals(offerAddProduct.getJSONName()); + } + + /** + * Tests the doPickAndExecute method when processing multiple products. + * Ensures that the appropriate operations are executed multiple times. + * + * @throws Exception if there is any issue during JSON processing or mock interaction + */ + @Test + public void testDoPickAndExecuteWithMultipleProducts() throws Exception { + JSONArray selectedLines = new JSONArray(); + for (int i = 0; i < 150; i++) { + JSONObject productJson = new JSONObject(); + productJson.put("id", "test-product-id-" + i); + selectedLines.put(productJson); + } + + try (MockedStatic obDalStatic = mockStatic(OBDal.class); + MockedStatic obProviderStatic = mockStatic(OBProvider.class)) { + + obDalStatic.when(OBDal::getInstance).thenReturn(obDal); + when(obDal.getProxy(eq(Product.ENTITY_NAME), anyString())).thenReturn(product); + + OBProvider obProvider = mock(OBProvider.class); + obProviderStatic.when(OBProvider::getInstance).thenReturn(obProvider); + when(obProvider.get(org.openbravo.model.pricing.priceadjustment.Product.class)) + .thenReturn(priceAdjustmentProduct); + + doNothing().when(priceAdjustmentProduct).setActive(anyBoolean()); + doNothing().when(priceAdjustmentProduct).setClient(any(Client.class)); + doNothing().when(priceAdjustmentProduct).setOrganization(any(Organization.class)); + doNothing().when(priceAdjustmentProduct).setPriceAdjustment(any(PriceAdjustment.class)); + doNothing().when(priceAdjustmentProduct).setProduct(any(Product.class)); + doNothing().when(obDal).save(any()); + doNothing().when(obDal).flush(); + doNothing().when(session).clear(); + + offerAddProduct.doPickAndExecute(priceAdjustment, selectedLines); + + verify(obDal, times(150)).save(any()); + verify(obDal, atLeast(1)).flush(); + verify(session, atLeast(1)).clear(); + } + } + + /** + * Tests the doPickAndExecute method when the input JSON is invalid. + * Expects a {@link JSONException} to be thrown. + * + * @throws Exception if the test encounters any unexpected errors + */ + @Test(expected = JSONException.class) + public void testDoPickAndExecuteWithInvalidJSON() throws Exception { + JSONArray selectedLines = new JSONArray(); + JSONObject invalidJson = new JSONObject(); + selectedLines.put(invalidJson); + + try (MockedStatic obDalStatic = mockStatic(OBDal.class)) { + obDalStatic.when(OBDal::getInstance).thenReturn(obDal); + offerAddProduct.doPickAndExecute(priceAdjustment, selectedLines); + } + } +} \ No newline at end of file diff --git a/src-test/src/com/smf/jobs/defaults/provider/JobsComponentProviderTest.java b/src-test/src/com/smf/jobs/defaults/provider/JobsComponentProviderTest.java new file mode 100644 index 000000000..65b67f454 --- /dev/null +++ b/src-test/src/com/smf/jobs/defaults/provider/JobsComponentProviderTest.java @@ -0,0 +1,121 @@ +package com.smf.jobs.defaults.provider; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.MockitoAnnotations; +import org.openbravo.client.kernel.ComponentProvider; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +import javax.enterprise.context.ApplicationScoped; + +/** + * Test suite for the JobsComponentProvider class, responsible for testing its functionality and annotations. + * This class verifies the following: + *
    + *
  • Presence and values of specific annotations.
  • + *
  • Constant definitions.
  • + *
  • Behavior of methods with and without expected exceptions.
  • + *
  • Proper structure and content of global component resources.
  • + *
+ */ +public class JobsComponentProviderTest { + + private JobsComponentProvider jobsComponentProvider; + + /** + * Sets up the testing environment by initializing mocks and the instance of the class under test. + */ + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + jobsComponentProvider = new JobsComponentProvider(); + } + + /** + * Tests the presence and value of the {@link ComponentProvider.Qualifier} annotation in the class under test. + */ + @Test + public void testComponentProviderQualifier() { + ComponentProvider.Qualifier qualifier = jobsComponentProvider.getClass().getAnnotation(ComponentProvider.Qualifier.class); + assertNotNull("ComponentProvider.Qualifier annotation should be present", qualifier); + assertEquals("Qualifier value should match COMPONENT_TYPE", + JobsComponentProvider.COMPONENT_TYPE, + qualifier.value()); + } + + /** + * Tests the value of the COMPONENT_TYPE constant. + */ + @Test + public void testConstantComponentType() { + assertEquals("COMPONENT_TYPE should be 'JOBSPR_CompProv'", + "JOBSPR_CompProv", + JobsComponentProvider.COMPONENT_TYPE); + } + + /** + * Verifies that calling getComponent with specific parameters throws an {@link IllegalArgumentException}. + * + * @throws IllegalArgumentException when an invalid component ID is passed. + */ + @Test(expected = IllegalArgumentException.class) + public void testGetComponentThrowsException() { + Map parameters = new HashMap<>(); + jobsComponentProvider.getComponent("testComponentId", parameters); + } + + /** + * Tests the contents and properties of the global component resources list. + * Ensures it is non-null, non-empty, contains specific elements, and has the expected size. + */ + @Test + public void testGetGlobalComponentResources() { + List globalResources = + jobsComponentProvider.getGlobalComponentResources(); + + assertNotNull("Global resources list should not be null", globalResources); + assertFalse("Global resources list should not be empty", globalResources.isEmpty()); + + assertEquals("Should have exactly 3 global resources", 3, globalResources.size()); + + boolean hasProcessRecordsJs = false; + boolean hasCloneRecordJs = false; + boolean hasCreateFromOrdersJs = false; + + for (Object resource : globalResources) { + String resourceString = resource.toString(); + if (resourceString.contains("processRecords.js")) { + hasProcessRecordsJs = true; + } + if (resourceString.contains("ob-clone-record.js")) { + hasCloneRecordJs = true; + } + if (resourceString.contains("createFromOrders.js")) { + hasCreateFromOrdersJs = true; + } + } + + assertTrue("Should contain processRecords.js", hasProcessRecordsJs); + assertTrue("Should contain ob-clone-record.js", hasCloneRecordJs); + assertTrue("Should contain createFromOrders.js", hasCreateFromOrdersJs); + } + + /** + * Verifies the presence of the {@link ApplicationScoped} annotation on the class under test. + */ + @Test + public void testApplicationScopedAnnotation() { + ApplicationScoped applicationScoped = + jobsComponentProvider.getClass().getAnnotation(ApplicationScoped.class); + assertNotNull("Class should be annotated with @ApplicationScoped", applicationScoped); + } +} \ No newline at end of file