Skip to content

Commit

Permalink
Port tests from JR 776 draft PR extending indexed-repeat coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
eyelidlessness committed Aug 22, 2024
1 parent fc30485 commit 59ccb8a
Showing 1 changed file with 168 additions and 1 deletion.
169 changes: 168 additions & 1 deletion packages/scenario/test/xpath/functions/indexed-repeat.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ import {
t,
title,
} from '@getodk/common/test/fixtures/xform-dsl/index.ts';
import { describe, expect, it } from 'vitest';
import { assert, describe, expect, it } from 'vitest';
import { intAnswer } from '../../../src/answer/ExpectedIntAnswer.ts';
import { stringAnswer } from '../../../src/answer/ExpectedStringAnswer.ts';
import { Scenario } from '../../../src/jr/Scenario.ts';

describe('Tests ported from JavaRosa', () => {
Expand Down Expand Up @@ -163,4 +164,170 @@ describe('Tests ported from JavaRosa', () => {
expect(scenario.answerOf('/data/some-group/last-value')).toEqualAnswer(intAnswer(33));
});
});

// https://github.com/getodk/javarosa/pull/776
describe('JavaRosa draft PR: "Add indexed-repeat tests"', () => {
/**
* **PORTING NOTES**
*
* - Test is ported to use a more general error check, and assertion
* messaging is updated accordingly. Error message is asserted **not to
* be** the error thrown by `@getodk/xpath` for missing function support,
* so we start with an expected failure throughout the suite.
*
* - Bind for `calc` is updated to reference `/data/calc`, as is clearly
* intended in the original draft PR.
*
* JR: firstArgNotChildOfRepeat_throwsException
*/
describe('first argument not child of a repeat', () => {
it.fails('produces an error', async () => {
let caught: unknown;

try {
// prettier-ignore
await 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'))
))
);
} catch (error) {
caught = error;
}

assert(caught instanceof Error);
expect(caught.message).not.toContain('function not defined: indexed-repeat');
});
});

/**
* **PORTING NOTES**
*
* - Removes superfluous position predicates on `outer_group`.
*
* JR: getsIndexedValueInSingleRepeat
*/
it.fails('gets an indexed value in a single repeat instance', async () => {
// prettier-ignore
const scenario = await 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.createNewRepeat('/data/outer_group/repeat');
// scenario.answer('/data/outer_group[1]/repeat[1]/inside', 'index1');
scenario.answer('/data/outer_group/repeat[1]/inside', 'index1');

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

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

scenario.answer('/data/index', '2');

expect(scenario.answerOf('/data/calc')).toEqualAnswer(stringAnswer('index2'));

scenario.answer('/data/index', '1');

expect(scenario.answerOf('/data/calc')).toEqualAnswer(stringAnswer('index1'));
});

/**
* **PORTING NOTES**
*
* - Updated body reference to `/data/repeat2/inside2`, as seems the likely
* intent for that input. (`xforms-engine` otherwise fails to parse the
* form when it encounters an input with the same reference as its parent
* repeat element)
*
* JR: getsIndexedValueUsingParallelRepeatPosition
*/
it.fails('gets an indexed value using parallel repeat position', async () => {
// prettier-ignore
const scenario = await 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');

expect(scenario.answerOf('/data/repeat2[1]/from_repeat1')).toEqualAnswer(
stringAnswer('index1')
);
expect(scenario.answerOf('/data/repeat2[2]/from_repeat1')).toEqualAnswer(
stringAnswer('index2')
);
});
});
});

0 comments on commit 59ccb8a

Please sign in to comment.