Skip to content

Commit

Permalink
FormDefTest.java - port second test focused on interaction of repeat/…
Browse files Browse the repository at this point in the history
…output

Includes two alternates:

1. Adapt direct port to use proposed `Scenario` API
2. Fix apparent mistakes in test: it doesn’t exercise `jr:itext`, correctly close the itext id attribute

Adds proposed `labelRef` to form fixture DSL.
  • Loading branch information
eyelidlessness committed May 16, 2024
1 parent b3279b0 commit ce8d575
Show file tree
Hide file tree
Showing 2 changed files with 261 additions and 0 deletions.
21 changes: 21 additions & 0 deletions packages/common/src/test/fixtures/xform-dsl/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,27 @@ export const label = (innerHtml: string): XFormsElement => {
return new StringLiteralXFormsElement('label', emptyMap(), innerHtml);
};

/**
* **PORTING NOTES**
*
* Since:
*
* 1. {@link label} does not support a `ref` attribute in its ported signature
* 2. I'm reticent to add new cases of signature overloading
* 3. I do not see any test cases in JavaRosa using both the form definition DSL
* with a structure like `<input><label ref="jr:itext(...)"/></input>`
* 4. I'm adding an alternate approach to an existing test which I believe
* **should** use that structure...
*
* This is a proposed addition to the DSL. Its name is intended to invoke the
* resulting structure (keeping it relatively close to the XML it produces),
* without introducing ambiguity about whether its {@link ref} parameter should
* fully specify the contents of a label's `ref` attribute (it should).
*/
export const labelRef = (ref: string) => {
return new TagXFormsElement('label', new Map([['ref', ref]]), []);
}

export const item = (value: Int | string, label: string): XFormsElement => {
return t('item', t('label', label), t('value', String(value)));
};
Expand Down
240 changes: 240 additions & 0 deletions packages/scenario/test/repeat-output.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
html,
input,
label,
labelRef,
mainInstance,
model,
repeat,
Expand Down Expand Up @@ -143,6 +144,245 @@ describe('Interaction between `<repeat>` and `<output>`', () => {
).toBe('Position: 2');
});
});

/**
* **PORTING NOTES**
*
* - The notes on the direct port/alternate pair above also apply to this
* direct port and its alternates.
*
* - The ported test does not appear to exercise the functionality
* expressed in the test description: while the form fixture does
* include a `jr:itext` definition with an `<output>` as described, the
* label under test does not reference it with a `jr:itext()` call to
* its id. Instead, the label is defined an inline `<output>` just as
* the previous port/alternate pair does. Observing this apparent
* discrepancy, an **additional alternate** test is included which fully
* exercises the test's apparent intent.
*
* - (Prediction) At time of writing, it is anticipated that the first
* alternate will pass, and the second alternate will fail. This is
* because we do not yet support `<output>` in itext definitions at all.
*
* - (Confirmation) The first alternate did pass, and second did fail, as
* expected. A minor surprise detail was also discovered: because web
* forms does not yet support `<output>` in itext translations, it was
* expected that the first label text assertion would fail with:
*
* - Expected: "Position: 1"
* - Received: "Position:"
*
* It initially failed with:
*
* - Expected: "Position: 1"
* - Received: ""
*
* This is because the form fixture (as ported) is defined without
* closing the itext item's `id` attribute. The resulting XML produced
* by the fixture DSL causes that `id` attribute to be truncated,
* losing its last character.
*
* - It's recommended that JavaRosa update this test, both to fully

This comment has been minimized.

Copy link
@lognaturel

lognaturel May 24, 2024

Member

Tracked at getodk/javarosa#759

* exercise the apparently intended `jr:itext` functionality, and to
* correct the fixture definition to close that itext `id` attribute.
* I've verified that both changes pass as expected in JavaRosa, and
* that the test fails as expected with only the `jr:itext` change
* (without closing the itext `id` attribute).
*/
describe('[direct port/alternate - output resolves relative references in `jr:itext`]', () => {
it.fails('resolves relative references in [`jr:itext`] itext', async () => {
const scenario = await Scenario.init(
'<output> with relative ref in translation',
html(
head(
title('output with relative ref in translation'),
model(
t(
'itext',
t(
'translation lang="Français"',
t(
'text id="/data/repeat/position_in_label:label',
t('value', 'Position: <output value="../position"/>')
)
)
),
mainInstance(
t(
'data id="relative-output"',
t('repeat jr:template=""', t('position'), t('position_in_label'))
)
),
bind('/data/repeat/position').type('int').calculate('position(..)'),
bind('/data/repeat/position_in_label').type('int')
)
),
body(
repeat(
'/data/repeat',
input(
'/data/repeat/position_in_label',
label('Position: <output value=" ../position "/>')
)
)
)
)
);

scenario.next('/data/repeat');
scenario.createNewRepeat({
assertCurrentReference: '/data/repeat',
});
scenario.next('/data/repeat[1]/position_in_label');

// FormEntryCaption caption = new FormEntryCaption(scenario.getFormDef(), scenario.getCurrentIndex());
let caption = new JRFormEntryCaption(scenario.getFormDef(), scenario.getCurrentIndex());

expect(caption.getQuestionText()).toBe('Position: 1');

scenario.next('/data/repeat');
scenario.createNewRepeat({
assertCurrentReference: '/data/repeat',
});
scenario.next('/data/repeat[2]/position_in_label');

// caption = new FormEntryCaption(scenario.getFormDef(), scenario.getCurrentIndex());
caption = new JRFormEntryCaption(scenario.getFormDef(), scenario.getCurrentIndex());

expect(caption.getQuestionText()).toBe('Position: 2');
});

it('produces the output of an expression with a relative reference (alternate #1)', async () => {
const scenario = await Scenario.init(
'<output> with relative ref in translation',
html(
head(
title('output with relative ref in translation'),
model(
t(
'itext',
t(
'translation lang="Français"',
t(
'text id="/data/repeat/position_in_label:label',
t('value', 'Position: <output value="../position"/>')
)
)
),
mainInstance(
t(
'data id="relative-output"',
t('repeat jr:template=""', t('position'), t('position_in_label'))
)
),
bind('/data/repeat/position').type('int').calculate('position(..)'),
bind('/data/repeat/position_in_label').type('int')
)
),
body(
repeat(
'/data/repeat',
input(
'/data/repeat/position_in_label',
label('Position: <output value=" ../position "/>')
)
)
)
)
);

scenario.next('/data/repeat');
scenario.createNewRepeat({
assertCurrentReference: '/data/repeat',
});
scenario.next('/data/repeat[1]/position_in_label');

expect(
scenario.proposed_getQuestionLabelText({
assertCurrentReference: '/data/repeat[1]/position_in_label',
})
).toBe('Position: 1');

scenario.next('/data/repeat');
scenario.createNewRepeat({
assertCurrentReference: '/data/repeat',
});
scenario.next('/data/repeat[2]/position_in_label');

expect(
scenario.proposed_getQuestionLabelText({
assertCurrentReference: '/data/repeat[2]/position_in_label',
})
).toBe('Position: 2');
});

it.fails(
'produces the output of an expression with a relative reference (alternate #2)',
async () => {
const scenario = await Scenario.init(
'<output> with relative ref in translation',
html(
head(
title('output with relative ref in translation'),
model(
t(
'itext',
t(
'translation lang="Français"',
t(
'text id="/data/repeat/position_in_label:label"',
t('value', 'Position: <output value="../position"/>')
)
)
),
mainInstance(
t(
'data id="relative-output"',
t('repeat jr:template=""', t('position'), t('position_in_label'))
)
),
bind('/data/repeat/position').type('int').calculate('position(..)'),
bind('/data/repeat/position_in_label').type('int')
)
),
body(
repeat(
'/data/repeat',
input(
'/data/repeat/position_in_label',
labelRef("jr:itext('/data/repeat/position_in_label:label')")
)
)
)
)
);

scenario.next('/data/repeat');
scenario.createNewRepeat({
assertCurrentReference: '/data/repeat',
});
scenario.next('/data/repeat[1]/position_in_label');

expect(
scenario.proposed_getQuestionLabelText({
assertCurrentReference: '/data/repeat[1]/position_in_label',
})
).toBe('Position: 1');

scenario.next('/data/repeat');
scenario.createNewRepeat({
assertCurrentReference: '/data/repeat',
});
scenario.next('/data/repeat[2]/position_in_label');

expect(
scenario.proposed_getQuestionLabelText({
assertCurrentReference: '/data/repeat[2]/position_in_label',
})
).toBe('Position: 2');
}
);
});
});
});
});

0 comments on commit ce8d575

Please sign in to comment.