55import org .junit .Test ;
66
77import java .io .IOException ;
8+ import java .util .Arrays ;
89
910import static org .hamcrest .MatcherAssert .assertThat ;
1011import static org .hamcrest .Matchers .is ;
@@ -30,21 +31,35 @@ public void stringNumberSeedConvertsWhenUsedInNodesetExpression() throws IOExcep
3031 title ("Randomize non-numeric seed" ),
3132 model (
3233 mainInstance (t ("data id=\" rand-non-numeric\" " ,
33- t ("choice" )
34+ t ("choices_numeric_seed" ),
35+ t ("choices_stringified_numeric_seed" )
3436 )),
3537 instance ("choices" ,
3638 item ("a" , "A" ),
37- item ("b" , "B" )
39+ item ("b" , "B" ),
40+ item ("c" , "C" ),
41+ item ("d" , "D" ),
42+ item ("e" , "E" ),
43+ item ("f" , "F" ),
44+ item ("g" , "G" ),
45+ item ("h" , "H" )
3846 ),
39- bind ("/data/choice" ).type ("string" )
47+ bind ("/data/choices_numeric_seed" ).type ("string" ),
48+ bind ("/data/choices_stringified_numeric_seed" ).type ("string" )
4049 )
4150 ),
4251 body (
43- select1Dynamic ("/data/choice" , "randomize(instance('choices')/root/item, '1')" )
52+ select1Dynamic ("/data/choices_numeric_seed" , "randomize(instance('choices')/root/item, 1234)" ),
53+ select1Dynamic ("/data/choices_stringified_numeric_seed" , "randomize(instance('choices')/root/item, '1234')" )
4454 )
4555 ));
46-
47- assertThat (scenario .choicesOf ("/data/choice" ).get (0 ).getValue (), is ("b" ));
56+ String [] shuffled = {"g" , "f" , "e" , "d" , "a" , "h" , "b" , "c" };
57+ String [] nodes = {"/data/choices_numeric_seed" , "/data/choices_stringified_numeric_seed" };
58+ for (int i = 0 ; i < shuffled .length ; i ++) {
59+ for (String node : nodes ) {
60+ assertThat (scenario .choicesOf (node ).get (i ).getValue (), is (shuffled [i ]));
61+ }
62+ }
4863 }
4964
5065 @ Test
@@ -54,21 +69,30 @@ public void stringNumberSeedConvertsWhenUsedInCalculate() throws IOException, XF
5469 title ("Randomize non-numeric seed" ),
5570 model (
5671 mainInstance (t ("data id=\" rand-non-numeric\" " ,
57- t ("choice" )
72+ t ("choices_numeric_seed" ),
73+ t ("choices_stringified_numeric_seed" )
5874 )),
5975 instance ("choices" ,
6076 item ("a" , "A" ),
61- item ("b" , "B" )
77+ item ("b" , "B" ),
78+ item ("c" , "C" ),
79+ item ("d" , "D" ),
80+ item ("e" , "E" ),
81+ item ("f" , "F" ),
82+ item ("g" , "G" ),
83+ item ("h" , "H" )
6284 ),
63- bind ("/data/choice" ).type ("string" ).calculate ("selected-at(join(' ', randomize(instance('choices')/root/item/label, '1')), 0)" )
85+ bind ("/data/choices_numeric_seed" ).type ("string" ).calculate ("join('', randomize(instance('choices')/root/item/label, 1234))" ),
86+ bind ("/data/choices_stringified_numeric_seed" ).type ("string" ).calculate ("join('', randomize(instance('choices')/root/item/label, '1234'))" )
6487 )
6588 ),
6689 body (
67- input ("/data/choice" )
90+ input ("/data/choices_numeric_seed" ),
91+ input ("/data/choices_stringified_numeric_seed" )
6892 )
6993 ));
70-
71- assertThat (scenario .answerOf ("/data/choice " ).getDisplayText (), is ("B " ));
94+ assertThat ( scenario . answerOf ( "/data/choices_numeric_seed" ). getDisplayText (), is ( scenario . answerOf ( "/data/choices_stringified_numeric_seed" ). getDisplayText ()));
95+ assertThat (scenario .answerOf ("/data/choices_numeric_seed " ).getDisplayText (), is ("GFEDAHBC " ));
7296 }
7397
7498 @ Test
@@ -82,7 +106,13 @@ public void stringTextSeedConvertsWhenUsedInNodesetExpression() throws IOExcepti
82106 )),
83107 instance ("choices" ,
84108 item ("a" , "A" ),
85- item ("b" , "B" )
109+ item ("b" , "B" ),
110+ item ("c" , "C" ),
111+ item ("d" , "D" ),
112+ item ("e" , "E" ),
113+ item ("f" , "F" ),
114+ item ("g" , "G" ),
115+ item ("h" , "H" )
86116 ),
87117 bind ("/data/choice" ).type ("string" )
88118 )
@@ -91,8 +121,10 @@ public void stringTextSeedConvertsWhenUsedInNodesetExpression() throws IOExcepti
91121 select1Dynamic ("/data/choice" , "randomize(instance('choices')/root/item, 'foo')" )
92122 )
93123 ));
94-
95- assertThat (scenario .choicesOf ("/data/choice" ).get (0 ).getValue (), is ("b" ));
124+ String [] shuffled = {"e" , "a" , "d" , "b" , "h" , "g" , "c" , "f" };
125+ for (int i = 0 ; i < shuffled .length ; i ++) {
126+ assertThat (scenario .choicesOf ("/data/choice" ).get (i ).getValue (), is (shuffled [i ]));
127+ }
96128 }
97129
98130 @ Test
@@ -106,17 +138,23 @@ public void stringTextSeedConvertsWhenUsedInCalculate() throws IOException, XFor
106138 )),
107139 instance ("choices" ,
108140 item ("a" , "A" ),
109- item ("b" , "B" )
141+ item ("b" , "B" ),
142+ item ("c" , "C" ),
143+ item ("d" , "D" ),
144+ item ("e" , "E" ),
145+ item ("f" , "F" ),
146+ item ("g" , "G" ),
147+ item ("h" , "H" )
110148 ),
111- bind ("/data/choice" ).type ("string" ).calculate ("selected-at( join(' ', randomize(instance('choices')/root/item/label, 'foo')), 0 )" )
149+ bind ("/data/choice" ).type ("string" ).calculate ("join('', randomize(instance('choices')/root/item/label, 'foo'))" )
112150 )
113151 ),
114152 body (
115153 input ("/data/choice" )
116154 )
117155 ));
118156
119- assertThat (scenario .answerOf ("/data/choice" ).getDisplayText (), is ("B " ));
157+ assertThat (scenario .answerOf ("/data/choice" ).getDisplayText (), is ("EADBHGCF " ));
120158 }
121159
122160 @ Test
@@ -155,4 +193,98 @@ public void seedInRepeatIsEvaluatedForEachInstance() throws IOException, XFormPa
155193 assertThat (scenario .choicesOf ("/data/repeat[2]/choice" ).get (0 ).getValue (), is ("b" ));
156194 assertThat (scenario .choicesOf ("/data/repeat[1]/choice" ).get (0 ).getValue (), is ("a" ));
157195 }
196+
197+ @ Test
198+ public void seedFromArbitraryInputCanBeUsed () throws IOException , XFormParser .ParseException {
199+ Scenario scenario = Scenario .init ("Randomize non-numeric seed" , html (
200+ head (
201+ title ("Randomize non-numeric seed" ),
202+ model (
203+ mainInstance (t ("data id=\" rand-non-numeric\" " ,
204+ t ("input" ),
205+ t ("choice" )
206+ )),
207+ instance ("choices" ,
208+ item ("a" , "A" ),
209+ item ("b" , "B" ),
210+ item ("c" , "C" ),
211+ item ("d" , "D" ),
212+ item ("e" , "E" ),
213+ item ("f" , "F" ),
214+ item ("g" , "G" ),
215+ item ("h" , "H" )
216+ ),
217+ bind ("/data/input" ).type ("geopoint" ),
218+ bind ("/data/choice" ).type ("string" )
219+ )
220+ ),
221+ body (
222+ input ("/data/input" ),
223+ select1Dynamic ("/data/choice" , "randomize(instance('choices')/root/item, /data/input)" )
224+ )
225+ ));
226+
227+ scenario .answer ("/data/input" , "-6.8137120026589315 39.29392995851879" );
228+ String [] shuffled = {"h" , "b" , "d" , "f" , "a" , "g" , "c" , "e" };
229+ for (int i = 0 ; i < shuffled .length ; i ++) {
230+ assertThat (scenario .choicesOf ("/data/choice" ).get (i ).getValue (), is (shuffled [i ]));
231+ }
232+ }
233+
234+ @ Test
235+ public void seed0FromNaNs () throws IOException , XFormParser .ParseException {
236+ Scenario scenario = Scenario .init ("Randomize non-numeric seed" , html (
237+ head (
238+ title ("Randomize non-numeric seed" ),
239+ model (
240+ mainInstance (t ("data id=\" rand-non-numeric\" " ,
241+ t ("input_emptystring" ),
242+ t ("input_somestring" ),
243+ t ("input_int" ),
244+ t ("choice_emptystring" ),
245+ t ("choice_somestring" ),
246+ t ("choice_int" )
247+ )),
248+ instance ("choices" ,
249+ item ("a" , "A" ),
250+ item ("b" , "B" ),
251+ item ("c" , "C" ),
252+ item ("d" , "D" ),
253+ item ("e" , "E" ),
254+ item ("f" , "F" ),
255+ item ("g" , "G" ),
256+ item ("h" , "H" )
257+ ),
258+ bind ("/data/input_emptystring" ).type ("string" ),
259+ bind ("/data/input_somestring" ).type ("string" ),
260+ bind ("/data/input_int" ).type ("int" )
261+ )
262+ ),
263+ body (
264+ input ("/data/input_emptystring" ),
265+ input ("/data/input_somestring" ),
266+ input ("/data/input_int" ),
267+ select1Dynamic ("/data/choice_emptystring" , "randomize(instance('choices')/root/item, /data/input_emptystring)" ),
268+ select1Dynamic ("/data/choice_somestring" , "randomize(instance('choices')/root/item, /data/input_somestring)" ),
269+ select1Dynamic ("/data/choice_int" , "randomize(instance('choices')/root/item, /data/input_int)" )
270+ )
271+ ));
272+
273+ scenario .answer ("/data/input_emptystring" , "" );
274+ scenario .answer ("/data/input_somestring" , "somestring" );
275+ scenario .answer ("/data/input_int" , "0" );
276+
277+ String [] shuffled_NaN_or_0 = {"c" , "b" , "h" , "a" , "f" , "d" , "g" , "e" };
278+ String [] shuffled_somestring = {"e" , "b" , "c" , "g" , "d" , "a" , "f" , "h" };
279+ assertThat ("somestring-seeded expected order is distinct from 0-seeded expected order" , !Arrays .equals (shuffled_NaN_or_0 , shuffled_somestring ));
280+ String [] shuffledfields = {"/data/choice_emptystring" , "/data/choice_int" };
281+ for (int i = 0 ; i < shuffled_NaN_or_0 .length ; i ++) {
282+ for (String shuffledfield : shuffledfields ) {
283+ assertThat (scenario .choicesOf (shuffledfield ).get (i ).getValue (), is (shuffled_NaN_or_0 [i ]));
284+ }
285+ }
286+ for (int i = 0 ; i < shuffled_somestring .length ; i ++) {
287+ assertThat (scenario .choicesOf ("/data/choice_somestring" ).get (i ).getValue (), is (shuffled_somestring [i ]));
288+ }
289+ }
158290}
0 commit comments