Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add indexed-repeat tests #776

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
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
18 changes: 9 additions & 9 deletions src/main/java/org/javarosa/xpath/expr/XPathFuncExpr.java
Original file line number Diff line number Diff line change
Expand Up @@ -970,15 +970,15 @@ public static Object ifThenElse(DataInstance model, EvaluationContext ec, XPathE
}

/**
* This provides a method of indexing fields stored in prior repeat groups.
* Provides a method of indexing fields stored in a repeat without writing an XPath filter expression.
* <p>
* args[0] = generic XPath expression to index
* args[1] = generic XPath expression for group to index
* args[2] = index number for group
* args[3] = generic XPath expression for add'l group to index (if 5 or 7 parameters passed)
* args[4] = index number for group (if 5 or 7 parameters passed)
* args[5] = generic XPath expression for add'l group to index (if 7 parameters passed)
* args[6] = index number for group (if 7 parameters passed)
* args[0] = reference to a field inside one or more repeats
* args[1] = generic XPath expression for repeat to index
* args[2] = index number for repeat instance
* args[3] = generic XPath expression for add'l repeat to index (if 5 or 7 parameters passed)
* args[4] = index number for repeat (if 5 or 7 parameters passed)
* args[5] = generic XPath expression for add'l repeat to index (if 7 parameters passed)
* args[6] = index number for repeat (if 7 parameters passed)
*/
public static Object indexedRepeat(DataInstance model, EvaluationContext ec, XPathExpression[] args, Object[] argVals) throws XPathTypeMismatchException {
// initialize target and context references
Expand All @@ -994,7 +994,7 @@ public static Object indexedRepeat(DataInstance model, EvaluationContext ec, XPa
for (int pathargi = 1, idxargi = 2; idxargi < args.length; pathargi += 2, idxargi += 2) {
// confirm that we were passed an XPath
if (!(args[pathargi] instanceof XPathPathExpr)) {
throw new XPathTypeMismatchException("indexed-repeat(): parameter " + (pathargi + 1) + " must be XPath repeat-group reference");
throw new XPathTypeMismatchException("indexed-repeat(): parameter " + (pathargi + 1) + " must be a reference to a repeat");
}
// confirm that the passed XPath is a parent of our overall target path
// Ensure we can deal with relative group refs by contextualizing with the EC's context ref
Expand Down
135 changes: 135 additions & 0 deletions src/test/java/org/javarosa/xpath/expr/IndexedRepeatTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package org.javarosa.xpath.expr;

import org.javarosa.test.Scenario;
import org.javarosa.xpath.XPathTypeMismatchException;
import org.junit.Test;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.instanceOf;
import static org.javarosa.core.test.AnswerDataMatchers.stringAnswer;
import static org.javarosa.test.BindBuilderXFormsElement.bind;
import static org.javarosa.test.XFormsElement.body;
import static org.javarosa.test.XFormsElement.group;
import static org.javarosa.test.XFormsElement.head;
import static org.javarosa.test.XFormsElement.html;
import static org.javarosa.test.XFormsElement.input;
import static org.javarosa.test.XFormsElement.mainInstance;
import static org.javarosa.test.XFormsElement.model;
import static org.javarosa.test.XFormsElement.repeat;
import static org.javarosa.test.XFormsElement.t;
import static org.javarosa.test.XFormsElement.title;
import static org.junit.Assert.fail;

public class IndexedRepeatTest {
@Test
public void firstArgNotChildOfRepeat_throwsException() throws Exception {
try {
Scenario.init("indexed-repeat", html(
head(
title("indexed-repeat"),
model(
mainInstance(t("data id=\"indexed-repeat\"",
t("outside"),
t("repeat",
t("inside")),
t("calc")
)),
bind("/data/calc").calculate("indexed-repeat(/data/outside, /data/repeat, 1)")
)
),
body(
input("/data/outside"),
repeat("/data/repeat",
input("/data/repeat/inside"))
))
);

fail("RuntimeException caused by XPathTypeMismatchException expected");
} catch (RuntimeException e) {
assertThat(e.getCause(), instanceOf(XPathTypeMismatchException.class));
}
}

@Test
public void getsIndexedValueInSingleRepeat() throws Exception {
Scenario scenario = Scenario.init("indexed-repeat", html(
head(
title("indexed-repeat"),
model(
mainInstance(t("data id=\"indexed-repeat\"",
t("index"),
t("outer_group", // included to clarify intended evaluation context for index references
t("repeat",
t("inside"))),
t("calc")
)),
bind("/data/calc").calculate("indexed-repeat(/data/outer_group/repeat/inside, /data/outer_group/repeat, ../index)")
)
),
body(
input("/data/index"),
group("/data/outer_group",
repeat("/data/outer_group/repeat",
input("/data/outer_group/repeat/inside")))
))
);

scenario.createNewRepeat("/data/outer_group[1]/repeat");
scenario.answer("/data/outer_group[1]/repeat[1]/inside", "index1");

scenario.createNewRepeat("/data/outer_group[1]/repeat");
scenario.answer("/data/outer_group[1]/repeat[2]/inside", "index2");

scenario.createNewRepeat("/data/outer_group[1]/repeat");
scenario.answer("/data/outer_group[1]/repeat[3]/inside", "index3");

scenario.answer("/data/index", "2");
assertThat(scenario.answerOf("/data/calc"), is(stringAnswer("index2")));

scenario.answer("/data/index", "1");
assertThat(scenario.answerOf("/data/calc"), is(stringAnswer("index1")));
}

@Test
public void getsIndexedValueUsingParallelRepeatPosition() throws Exception {
Scenario scenario = Scenario.init("indexed-repeat", html(
head(
title("indexed-repeat"),
model(
mainInstance(t("data id=\"indexed-repeat\"",
t("repeat1",
t("inside1")),

t("repeat2",
t("inside2"),
t("from_repeat1"))
)),
bind("/data/repeat2/from_repeat1").calculate("indexed-repeat(/data/repeat1/inside1, /data/repeat1, position(..))")
)
),
body(
repeat("/data/repeat1",
input("/data/repeat1/inside1")),

repeat("/data/repeat2",
input("/data/repeat2/inside2"))
))
);

scenario.createNewRepeat("/data/repeat1");
scenario.createNewRepeat("/data/repeat2");
scenario.answer("/data/repeat1[1]/inside1", "index1");

scenario.createNewRepeat("/data/repeat1");
scenario.createNewRepeat("/data/repeat2");
scenario.answer("/data/repeat1[2]/inside1", "index2");

scenario.createNewRepeat("/data/repeat1");
scenario.createNewRepeat("/data/repeat2");
scenario.answer("/data/repeat1[3]/inside1", "index3");

assertThat(scenario.answerOf("/data/repeat2[1]/from_repeat1"), is(stringAnswer("index1")));
assertThat(scenario.answerOf("/data/repeat2[2]/from_repeat1"), is(stringAnswer("index2")));
}
}