Skip to content

Commit 23225a5

Browse files
megha1807jkuester
andauthored
fix(medic#8226): skip form pages where all contents are hidden (medic#10917)
Co-authored-by: Joshua Kuestersteffen <[email protected]>
1 parent 995bbf0 commit 23225a5

6 files changed

Lines changed: 118 additions & 18 deletions

File tree

tests/e2e/default/enketo/db-object-widget.wdio-spec.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,11 @@ describe('DB Object Widget', () => {
7272
name: offlineUser.contact.name,
7373
sex: offlineUser.contact.sex
7474
},
75-
user_contact: {
76-
_id: offlineUser.contact._id,
77-
name: offlineUser.contact.name,
78-
sex: offlineUser.contact.sex
79-
},
75+
},
76+
user_contact: {
77+
_id: offlineUser.contact._id,
78+
name: offlineUser.contact.name,
79+
sex: offlineUser.contact.sex
8080
},
8181
people: {
8282
user_contact: {
-1 Bytes
Binary file not shown.

tests/e2e/default/enketo/forms/db-object-form.xml

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
</translation>
1515
</itext>
1616
<instance>
17-
<data id="db-object-form" version="2024-09-05 00:00:00" prefix="J1!db-object-form!" delimiter="#">
17+
<data id="db-object-form" version="2026-04-30 00:00:00" prefix="J1!db-object-form!" delimiter="#">
1818
<inputs>
1919
<meta>
2020
<location>
@@ -29,12 +29,12 @@
2929
<name/>
3030
<sex/>
3131
</user>
32-
<user_contact>
33-
<_id/>
34-
<name/>
35-
<sex/>
36-
</user_contact>
3732
</inputs>
33+
<user_contact>
34+
<_id/>
35+
<name/>
36+
<sex/>
37+
</user_contact>
3838
<people>
3939
<user_contact>
4040
<_id/>
@@ -55,9 +55,9 @@
5555
<bind nodeset="/data/inputs/user/contact_id" type="string"/>
5656
<bind nodeset="/data/inputs/user/name" type="string"/>
5757
<bind nodeset="/data/inputs/user/sex" type="string"/>
58-
<bind nodeset="/data/inputs/user_contact/_id" type="string" calculate="../../user/contact_id"/>
59-
<bind nodeset="/data/inputs/user_contact/name" type="string"/>
60-
<bind nodeset="/data/inputs/user_contact/sex" type="string"/>
58+
<bind nodeset="/data/user_contact/_id" type="string" calculate="../../inputs/user/contact_id"/>
59+
<bind nodeset="/data/user_contact/name" type="string"/>
60+
<bind nodeset="/data/user_contact/sex" type="string"/>
6161
<bind nodeset="/data/people/user_contact/_id" type="string" calculate="../../../inputs/user/contact_id"/>
6262
<bind nodeset="/data/people/user_contact/name" type="string"/>
6363
<bind nodeset="/data/people/user_contact/sex" type="string"/>
@@ -69,12 +69,12 @@
6969
<h:body class="pages">
7070
<group ref="/data/inputs">
7171
<group ref="/data/inputs/user">
72-
<input ref="/data/inputs/user/contact_id" appearance="hidden select-contact type-person"/>
73-
</group>
74-
<group ref="/data/inputs/user_contact">
75-
<input ref="/data/inputs/user_contact/_id" appearance="hidden select-contact type-person"/>
72+
<input ref="/data/inputs/user/contact_id" appearance="select-contact type-person"/>
7673
</group>
7774
</group>
75+
<group appearance="hidden" ref="/data/user_contact">
76+
<input ref="/data/user_contact/_id" appearance="select-contact type-person"/>
77+
</group>
7878
<group appearance="field-list" ref="/data/people">
7979
<group ref="/data/people/user_contact">
8080
<input ref="/data/people/user_contact/_id" appearance="hidden select-contact type-person"/>

webapp/src/js/enketo/widgets.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
require( './widgets/display-base64-image' ),
3232
require( './widgets/dynamic-url' ),
3333
require( './widgets/draw' ),
34+
require( './widgets/hidden-group' ),
3435
];
3536

3637
module.exports = widgets;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
'use strict';
2+
const Widget = require('enketo-core/src/js/widget').default;
3+
4+
/**
5+
* Widget that disables groups with the `hidden` appearance. This prevents Enketo from rendering an empty page for
6+
* a root-level hidden group.
7+
*
8+
* @extends Widget
9+
*/
10+
class HiddenGroup extends Widget {
11+
/**
12+
* Matches groups that have the `hidden` appearance.
13+
* These are top-level groups that should not be rendered as a page.
14+
*/
15+
static get selector() {
16+
return '.or-group-data.or-appearance-hidden';
17+
}
18+
19+
_init() {
20+
this.element.classList.add('disabled');
21+
}
22+
}
23+
24+
module.exports = HiddenGroup;
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { expect } from 'chai';
2+
import sinon from 'sinon';
3+
const $ = require('jquery');
4+
5+
const HiddenGroup = require('../../../../../src/js/enketo/widgets/hidden-group');
6+
7+
const testId = 'hidden-group-test';
8+
const buildHtml = (html: string) => document.body.insertAdjacentHTML(
9+
'afterbegin',
10+
`<div id="${testId}">${html}</div>`
11+
);
12+
13+
describe('HiddenGroup Widget', () => {
14+
15+
afterEach(() => {
16+
sinon.restore();
17+
$(`#${testId}`).remove();
18+
});
19+
20+
describe('selector', () => {
21+
it('matches groups with both group and hidden appearances', () => {
22+
buildHtml(`
23+
<section class="or-group-data or-appearance-hidden">
24+
<div class="question or-appearance-hidden"></div>
25+
</section>
26+
`);
27+
const el = document.querySelector('.or-group-data.or-appearance-hidden');
28+
expect(el).to.not.be.null;
29+
expect(el!.matches(HiddenGroup.selector)).to.be.true;
30+
});
31+
32+
it('does not match groups with only group appearance', () => {
33+
buildHtml(`<section class="or-group-data"></section>`);
34+
const el = document.querySelector(`#${testId} .or-group-data`);
35+
expect(el!.matches(HiddenGroup.selector)).to.be.false;
36+
});
37+
38+
it('does not match groups with only hidden appearance', () => {
39+
buildHtml(`<section class="or-appearance-hidden"></section>`);
40+
const el = document.querySelector(`#${testId} .or-appearance-hidden`);
41+
expect(el!.matches(HiddenGroup.selector)).to.be.false;
42+
});
43+
});
44+
45+
describe('_init', () => {
46+
it('adds disabled class to group with hidden appearance', () => {
47+
buildHtml(`
48+
<form class="or">
49+
<section class="or-group-data or-appearance-hidden">
50+
<div class="question or-appearance-hidden"></div>
51+
</section>
52+
</form>
53+
`);
54+
const el = document.querySelector(HiddenGroup.selector) as HTMLElement;
55+
new HiddenGroup(el, {});
56+
expect(el.classList.contains('disabled')).to.be.true;
57+
});
58+
59+
it('preserves existing classes when adding disabled', () => {
60+
buildHtml(`
61+
<form class="or">
62+
<section class="or-group-data or-appearance-hidden">
63+
<div class="question or-appearance-hidden"></div>
64+
</section>
65+
</form>
66+
`);
67+
const el = document.querySelector(HiddenGroup.selector) as HTMLElement;
68+
new HiddenGroup(el, {});
69+
expect(el.classList.contains('or-group-data')).to.be.true;
70+
expect(el.classList.contains('or-appearance-hidden')).to.be.true;
71+
expect(el.classList.contains('disabled')).to.be.true;
72+
});
73+
});
74+
75+
});

0 commit comments

Comments
 (0)