Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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())
Expand Down Expand Up @@ -459,6 +466,103 @@ class EntitiesTest {
)
}

@Test
fun `filling form with create or update in repeats makes entities available`() {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be tempted to test this at the Collect UI level instead given that we have to set up the full "stack" of entity plugins and that's not really ever done in EntitiesTest. Generally anything that interacts with the "data" layer (EntitiesRepository) is tested at the full app level to make sure everything is glued together. For example, this test uses an EntitiesRespoistory for its initial state, but doesn't check the final state (because that requires more components to be hooked in). Writing this as a full app test would get you a test of the full flow.

Alternatively, we could add some more realistic full flow tests in entities that sets the whole thing up to test flows like this without needing an app level test.

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<StringData>("/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(
Expand Down