From d0cd2816fb3f30c2324eec918e2fa4feb7444696 Mon Sep 17 00:00:00 2001 From: Shubham Goyal Date: Thu, 31 Aug 2023 13:28:39 -0500 Subject: [PATCH 1/4] Tests for case list endpoints with inline case search enabled --- .../tests/MultiSelectCaseClaimTest.java | 71 +++++++++++++++++-- .../case_claim_with_multi_select/suite.xml | 68 ++++++++++++++++++ 2 files changed, 133 insertions(+), 6 deletions(-) diff --git a/src/test/java/org/commcare/formplayer/tests/MultiSelectCaseClaimTest.java b/src/test/java/org/commcare/formplayer/tests/MultiSelectCaseClaimTest.java index 500d94ee4..994ae73cc 100644 --- a/src/test/java/org/commcare/formplayer/tests/MultiSelectCaseClaimTest.java +++ b/src/test/java/org/commcare/formplayer/tests/MultiSelectCaseClaimTest.java @@ -2,22 +2,20 @@ import static org.commcare.formplayer.util.Constants.TOGGLE_SESSION_ENDPOINTS; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; + +import com.google.common.collect.Multimap; import org.apache.commons.lang3.ArrayUtils; import org.commcare.formplayer.beans.FormEntryResponseBean; import org.commcare.formplayer.beans.NewFormResponse; import org.commcare.formplayer.beans.menus.CommandListResponseBean; import org.commcare.formplayer.beans.menus.EntityListResponse; -import org.commcare.formplayer.junit.RestoreFactoryAnswer; import org.commcare.formplayer.mocks.FormPlayerPropertyManagerMock; import org.commcare.formplayer.utils.MockRequestUtils; import org.commcare.formplayer.utils.WithHqUser; @@ -27,7 +25,6 @@ import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.mockito.Captor; -import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.cache.CacheManager; @@ -53,6 +50,10 @@ public class MultiSelectCaseClaimTest extends BaseTestClass { @Captor ArgumentCaptor> requestDataCaptor; + + @Captor + ArgumentCaptor> queryRequestDataCaptor; + private MockRequestUtils mockRequest; @Override @@ -332,4 +333,62 @@ public void testMultiSelectEndpointWithClaim_ValidSelection() throws Exception { checkForSelectedEntitiesInstance(formResponse.getSessionId(), selectedValues); } } + + @Test + @WithHqUser(enabledToggles = {TOGGLE_SESSION_ENDPOINTS}) + public void testCaseListEndpointWithInlineCaseSearch() throws Exception { + try (MockRequestUtils.VerifiedMock ignore = mockRequest.mockQuery( + "query_responses/case_search_multi_select_response.xml")) { + EntityListResponse response = sessionNavigateWithEndpoint(APP_NAME, + "inline_case_search_list_without_selection", + null, + EntityListResponse.class); + assertNotNull(response.getEntities()); + } + } + + + @Test + @WithHqUser(enabledToggles = {TOGGLE_SESSION_ENDPOINTS}) + public void testCaseListSelectionEndpointWithInlineCaseSearch() throws Exception { + String[] selectedValues = new String[]{"94f8d030-c6f9-49e0-bc3f-5e0cdbf10c18", + "0156fa3e-093e-4136-b95c-01b13dae66c7", + "0156fa3e-093e-4136-b95c-01b13dae66c8"}; + String selectedValuesArg = String.join(",", selectedValues); + HashMap endpointArgs = new HashMap<>(); + endpointArgs.put("selected_cases", selectedValuesArg); + try (MockRequestUtils.VerifiedMock ignore = mockRequest.mockQuery( + "query_responses/case_search_multi_select_response.xml", 2)) { + CommandListResponseBean response = sessionNavigateWithEndpoint(APP_NAME, + "inline_case_search_list", + endpointArgs, + CommandListResponseBean.class); + assertEquals(response.getCommands().length, 1); + } + verify(webClientMock, times(2)).postFormData(urlCaptor.capture(), + queryRequestDataCaptor.capture()); + + assertEquals("http://localhost:8000/a/shubham/phone/case_fixture/d54c955d883b4dd99f57571649271af1/", urlCaptor.getAllValues().get(0)); + Multimap requestData = queryRequestDataCaptor.getAllValues().get(0); + assertEquals(String.join(",",requestData.get("case_id")), String.join(",",selectedValues)); + } + + @Test + @WithHqUser(enabledToggles = {TOGGLE_SESSION_ENDPOINTS}) + public void testFormEndpointWithInlineCaseSearch() throws Exception { + String[] selectedValues = new String[]{"94f8d030-c6f9-49e0-bc3f-5e0cdbf10c18", + "0156fa3e-093e-4136-b95c-01b13dae66c7", + "0156fa3e-093e-4136-b95c-01b13dae66c8"}; + String selectedValuesArg = String.join(",", selectedValues); + HashMap endpointArgs = new HashMap<>(); + endpointArgs.put("selected_cases", selectedValuesArg); + try (MockRequestUtils.VerifiedMock ignore = mockRequest.mockQuery( + "query_responses/case_search_multi_select_response.xml", 2)) { + NewFormResponse formResponse = sessionNavigateWithEndpoint(APP_NAME, + "inline_case_search_form", + endpointArgs, + NewFormResponse.class); + checkForSelectedEntitiesInstance(formResponse.getSessionId(), selectedValues); + } + } } diff --git a/src/test/resources/archives/case_claim_with_multi_select/suite.xml b/src/test/resources/archives/case_claim_with_multi_select/suite.xml index 14cb56e55..6d8a88522 100644 --- a/src/test/resources/archives/case_claim_with_multi_select/suite.xml +++ b/src/test/resources/archives/case_claim_with_multi_select/suite.xml @@ -259,6 +259,33 @@ + +
http://openrosa.org/formdesigner/5CCB1614-68B3-44C0-A166-D63AA7C1D4FB
+ + + + + + + + + + + + + + + + + + + + + + + + +
@@ -283,6 +310,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From d38c9a1c204a698d2773ea4b8895109b06ba7a8d Mon Sep 17 00:00:00 2001 From: Shubham Goyal Date: Fri, 8 Sep 2023 12:49:16 -0500 Subject: [PATCH 2/4] Makes multi select instance available to stack ops while endpoint processing --- .../services/MenuSessionRunnerService.java | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/commcare/formplayer/services/MenuSessionRunnerService.java b/src/main/java/org/commcare/formplayer/services/MenuSessionRunnerService.java index a9f41ab25..0e192d196 100644 --- a/src/main/java/org/commcare/formplayer/services/MenuSessionRunnerService.java +++ b/src/main/java/org/commcare/formplayer/services/MenuSessionRunnerService.java @@ -1,6 +1,5 @@ package org.commcare.formplayer.services; -import static org.commcare.data.xml.VirtualInstances.buildSelectedValuesInstance; import static org.commcare.formplayer.util.Constants.TOGGLE_SESSION_ENDPOINTS; import static org.commcare.formplayer.util.Constants.TOGGLE_SPLIT_SCREEN_CASE_SEARCH; import static org.javarosa.core.model.instance.ExternalDataInstance.JR_SELECTED_ENTITIES_REFERENCE; @@ -73,6 +72,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Hashtable; +import java.util.Map; import java.util.Vector; import javax.annotation.Resource; @@ -705,7 +705,9 @@ public BaseResponseBean advanceSessionWithEndpoint(MenuSession menuSession, Stri EvaluationContext evalContext = sessionWrapper.getEvaluationContext(); try { if (endpointArgs != null) { - processEndpointArgumentsForVirualInstance(endpoint, endpointArgs); + Map instances = processEndpointArgumentsForVirualInstance(endpoint, + endpointArgs); + evalContext = evalContext.spawnWithCleanLifecycle(instances); Endpoint.populateEndpointArgumentsToEvaluationContext(endpoint, endpointArgs, evalContext); } } catch (Endpoint.InvalidEndpointArgumentsException ieae) { @@ -722,7 +724,6 @@ public BaseResponseBean advanceSessionWithEndpoint(MenuSession menuSession, Stri throw new RuntimeException( String.format("Invalid arguments supplied for link.%s%s", missingMessage, unexpectedMessage)); } - // Sync requests aren't run when executing operations, so stop and check for them after each operation for (StackOperation op : endpoint.getStackOperations()) { sessionWrapper.executeStackOperations(new Vector<>(Arrays.asList(op)), evalContext); @@ -745,16 +746,20 @@ public BaseResponseBean advanceSessionWithEndpoint(MenuSession menuSession, Stri return advanceSessionWithSelections(menuSession, selections, null); } - private void processEndpointArgumentsForVirualInstance(Endpoint endpoint, + private Map processEndpointArgumentsForVirualInstance(Endpoint endpoint, HashMap argumentValues) { + Map instances = new HashMap<>(); for (EndpointArgument argument : endpoint.getArguments()) { if(argument.isInstanceArgument()){ String argumentValue = argumentValues.get(argument.getId()); String instanceSrc = argument.getInstanceSrc(); if (instanceSrc.contentEquals(JR_SELECTED_ENTITIES_REFERENCE)) { String[] selectedEntites = argumentValue.split(","); - String uuid = storeInSelectedEntitiesInstance(argument, selectedEntites); - argumentValues.put(argument.getId(), uuid); + Pair guidAndInstance = storeInSelectedEntitiesInstance(argument, + selectedEntites); + argumentValues.put(argument.getId(), guidAndInstance.first); + ExternalDataInstance instance = guidAndInstance.second; + instances.put(instance.getInstanceId(), instance); } else { throw new RuntimeException( "Invalid instance-src defined for argument " + argument.getId() + " for endpoint " @@ -762,13 +767,12 @@ private void processEndpointArgumentsForVirualInstance(Endpoint endpoint, } } } + return instances; } - private String storeInSelectedEntitiesInstance(EndpointArgument argument, String[] selectedEntites) { - Pair guidAndInstance = - VirtualInstances.storeSelectedValuesInInstance(virtualDataInstanceService, selectedEntites, + private Pair storeInSelectedEntitiesInstance(EndpointArgument argument, String[] selectedEntites) { + return VirtualInstances.storeSelectedValuesInInstance(virtualDataInstanceService, selectedEntites, argument.getInstanceId()); - return guidAndInstance.first; } public CaseSearchHelper getCaseSearchHelper() { From 8de2633c8c79c0038759bc191ca1cd6844391671 Mon Sep 17 00:00:00 2001 From: Shubham Goyal Date: Fri, 8 Sep 2023 12:50:21 -0500 Subject: [PATCH 3/4] Fix querydata processing by removing toString on a list --- .../org/commcare/formplayer/services/MenuSessionFactory.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/commcare/formplayer/services/MenuSessionFactory.java b/src/main/java/org/commcare/formplayer/services/MenuSessionFactory.java index 8f8ab4e5c..01cd567e7 100644 --- a/src/main/java/org/commcare/formplayer/services/MenuSessionFactory.java +++ b/src/main/java/org/commcare/formplayer/services/MenuSessionFactory.java @@ -30,6 +30,7 @@ import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; +import java.util.Collection; import java.util.Vector; import datadog.trace.api.Trace; @@ -133,7 +134,7 @@ public void rebuildSessionFromFrame(MenuSession menuSession, CaseSearchHelper ca throw new CommCareSessionException("Query URL format error: " + e.getMessage(), e); } ImmutableMultimap.Builder dataBuilder = ImmutableMultimap.builder(); - step.getExtras().forEach((key, value) -> dataBuilder.put(key, value.toString())); + step.getExtras().forEach((key, value) -> dataBuilder.putAll(key, ((Collection)value))); try { ExternalDataInstance searchDataInstance = caseSearchHelper.getRemoteDataInstance( queryScreen.getQueryDatum().getDataId(), From c0645d0e1897fcbccfec2fdbe4be6a42d0cf63f4 Mon Sep 17 00:00:00 2001 From: Shubham Goyal Date: Tue, 12 Sep 2023 11:12:45 -0500 Subject: [PATCH 4/4] update core to latest formplayer head --- libs/commcare | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/commcare b/libs/commcare index 3f6272966..7aea837bf 160000 --- a/libs/commcare +++ b/libs/commcare @@ -1 +1 @@ -Subproject commit 3f62729669f23f4b1644a381d106d4522e440084 +Subproject commit 7aea837bf039d7ebf50d1299de5fc79f1b8dedd5