diff --git a/entities/src/test/java/org/odk/collect/entities/javarosa/EntitiesTest.kt b/entities/src/test/java/org/odk/collect/entities/javarosa/EntitiesTest.kt index 6b63a04467a..bb7aebf857f 100644 --- a/entities/src/test/java/org/odk/collect/entities/javarosa/EntitiesTest.kt +++ b/entities/src/test/java/org/odk/collect/entities/javarosa/EntitiesTest.kt @@ -3,9 +3,12 @@ package org.odk.collect.entities.javarosa import org.hamcrest.CoreMatchers.equalTo import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.containsInAnyOrder +import org.javarosa.core.model.FormDef import org.javarosa.core.model.data.StringData import org.javarosa.core.model.data.UncastData import org.javarosa.core.model.instance.TreeElement +import org.javarosa.form.api.FormEntryController +import org.javarosa.form.api.FormEntryModel import org.javarosa.test.BindBuilderXFormsElement.bind import org.javarosa.test.Scenario import org.javarosa.test.XFormsElement.body @@ -18,6 +21,7 @@ import org.javarosa.test.XFormsElement.mainInstance import org.javarosa.test.XFormsElement.model import org.javarosa.test.XFormsElement.repeat import org.javarosa.test.XFormsElement.select1 +import org.javarosa.test.XFormsElement.select1Dynamic import org.javarosa.test.XFormsElement.setvalue import org.javarosa.test.XFormsElement.t import org.javarosa.test.XFormsElement.title @@ -26,11 +30,14 @@ import org.javarosa.xform.util.XFormUtils import org.junit.After import org.junit.Before import org.junit.Test +import org.odk.collect.entities.javarosa.filter.LocalEntitiesFilterStrategy import org.odk.collect.entities.javarosa.finalization.EntitiesExtra import org.odk.collect.entities.javarosa.finalization.EntityFormFinalizationProcessor import org.odk.collect.entities.javarosa.finalization.FormEntity import org.odk.collect.entities.javarosa.parse.EntityXFormParserFactory import org.odk.collect.entities.javarosa.spec.EntityAction +import org.odk.collect.entities.storage.Entity +import org.odk.collect.entities.storage.InMemEntitiesRepository class EntitiesTest { private val entityXFormParserFactory = EntityXFormParserFactory(XFormParserFactory()) @@ -459,6 +466,103 @@ class EntitiesTest { ) } + @Test + fun `filling form with create or update in repeats makes entities available`() { + val entitiesRepository = InMemEntitiesRepository() + entitiesRepository.save("people", Entity.New("1", "Roman Roy")) + + val controllerSupplier: (FormDef) -> FormEntryController = { formDef -> + FormEntryController(FormEntryModel(formDef)).also { + it.addFilterStrategy(LocalEntitiesFilterStrategy(entitiesRepository)) + } + } + + val scenario = Scenario.init( + "Create or update entities from repeats form", + html( + listOf("entities" to "http://www.opendatakit.org/xforms/entities"), + head( + title("Create or update entities from repeats form"), + model( + listOf(Pair("entities:entities-version", "2025.1.0")), + mainInstance( + t( + "data id=\"create-or-update-entities-from-repeats-form\"", + t( + "people", + t("person"), + t("new_uuid"), + t("name"), + t( + "meta", + t( + "entity dataset=\"people\" create=\"1\" update=\"1\" id=\"\"", + t("label") + ) + ) + ) + ) + ), + t("instance id=\"people\" src=\"jr://file-csv/people.csv\""), + bind("/data/people/person").type("string"), + bind("/data/people/new_uuid").type("string").calculate("once(uuid())").relevant("/data/people/person = ''"), + bind("/data/people/name").type("string").withAttribute("entities", "saveto", "name"), + bind("/data/people/meta/entity/@create").type("string").calculate("/data/people/person = ''"), + bind("/data/people/meta/entity/@update").type("string").calculate("/data/people/person != ''"), + bind("/data/people/meta/entity/@id").type("string").calculate("if(/data/people/person = '', /data/people/new_uuid , /data/people/person)"), + bind("/data/people/meta/entity/label").type("string").calculate("/data/people/name"), + setvalue("odk-instance-first-load", "/data/people/meta/entity/@id", "uuid()"), + ) + ), + body( + repeat( + "/data/people", + select1Dynamic( + "/data/people/person", + "instance('people')/root/item", + "name", + "label" + ), + input("/data/people/name"), + setvalue("odk-new-repeat", "/data/people/meta/entity/@id", "uuid()") + ) + ) + ), + controllerSupplier + ) + + scenario.formEntryController.addPostProcessor(EntityFormFinalizationProcessor()) + + scenario.answer("/data/people[1]/name", "Tom Wambsgans") + scenario.createNewRepeat("/data/people") + scenario.answer("/data/people[2]/person", "1") + scenario.answer("/data/people[2]/name", "Romulus Roy") + scenario.finalizeInstance() + + val entities = scenario.formEntryController.model.extras.get(EntitiesExtra::class.java).entities + assertThat(entities.size, equalTo(2)) + + assertThat( + entities, + containsInAnyOrder( + FormEntity( + EntityAction.CREATE, + "people", + scenario.answerOf("/data/people[1]/meta/entity/@id").value as String?, + "Tom Wambsgans", + listOf(Pair("name", "Tom Wambsgans")) + ), + FormEntity( + EntityAction.UPDATE, + "people", + "1", + "Romulus Roy", + listOf(Pair("name", "Romulus Roy")) + ) + ) + ) + } + @Test fun `filling form with create in nested repeats makes entities available`() { val scenario = Scenario.init(