Skip to content

Commit 503bb7d

Browse files
feat(#675): support duplicate_check contact form property (#677)
1 parent a2b1271 commit 503bb7d

File tree

6 files changed

+103
-4
lines changed

6 files changed

+103
-4
lines changed

src/lib/upload-forms.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const {
1515
} = require('./forms-utils');
1616

1717
const SUPPORTED_PROPERTIES = ['context', 'icon', 'title', 'xml2sms', 'subject_key', 'hidden_fields'];
18+
const CONTACT_DUPLICATE_CHECK_PROPERTY = 'duplicate_check';
1819
const FORM_EXTENSTION = '.xml';
1920
const FORM_PROPERTIES_EXTENSION = '.properties.json';
2021
const FORM_MEDIA_MATCHER = /(.+)-media$/;
@@ -49,6 +50,11 @@ const execute = async (projectDir, subDirectory, options) => {
4950
return;
5051
}
5152

53+
const PROPERTIES = [...SUPPORTED_PROPERTIES];
54+
if (subDirectory === 'contact') {
55+
PROPERTIES.push(CONTACT_DUPLICATE_CHECK_PROPERTY);
56+
}
57+
5258
const fileNames = argsFormFilter(formsDir, FORM_EXTENSTION, options);
5359
for (const fileName of fileNames) {
5460
log.info(`Preparing form for upload: ${fileName}…`);
@@ -85,12 +91,12 @@ const execute = async (projectDir, subDirectory, options) => {
8591
};
8692

8793
const propertiesPath = `${formsDir}/${baseFileName}${FORM_PROPERTIES_EXTENSION}`;
88-
updateFromPropertiesFile(doc, propertiesPath);
94+
updateFromPropertiesFile(doc, propertiesPath, PROPERTIES);
8995

9096
doc._attachments = mediaDirExists ? attachmentsFromDir(mediaDir) : {};
9197
doc._attachments.xml = attachmentFromFile(xformPath);
9298

93-
const properties = SUPPORTED_PROPERTIES.concat('internalId');
99+
const properties = PROPERTIES.concat('internalId');
94100

95101
const changes = await warnUploadOverwrite.preUploadForm(db, doc, xml, properties);
96102
if (changes) {
@@ -112,15 +118,15 @@ module.exports = {
112118
execute
113119
};
114120

115-
const updateFromPropertiesFile = (doc, path) => {
121+
const updateFromPropertiesFile = (doc, path, supported_properties) => {
116122
if (fs.exists(path)) {
117123

118124
const ignoredKeys = [];
119125
const properties = fs.readJson(path);
120126

121127
Object.keys(properties).forEach(key => {
122128
if (typeof properties[key] !== 'undefined') {
123-
if (SUPPORTED_PROPERTIES.includes(key)) {
129+
if (supported_properties.includes(key)) {
124130
doc[key] = properties[key];
125131
} else if (key === 'internalId') {
126132
log.warn(`DEPRECATED: ${path}. Please do not manually set internalId in .properties.json for new projects. Support for configuring this value will be dropped. Please see https://github.com/medic/cht-core/issues/3342.`);
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"duplicate_check": {
3+
"expression": "levenshteinEq(current.name, existing.name, 3) && ageInYears(current) === ageInYears(existing)",
4+
"disabled": true
5+
}
6+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0"?>
2+
<h:html xmlns="http://www.w3.org/2002/xforms" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:jr="http://openrosa.org/javarosa" xmlns:orx="http://openrosa.org/xforms/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
3+
<h:head>
4+
<h:title>Merge properties</h:title>
5+
<model>
6+
<instance>
7+
<data id="example" version="2015-06-05">
8+
<name/>
9+
</data>
10+
<meta>
11+
<instanceID/>
12+
</meta>
13+
</instance>
14+
<bind nodeset="/data/name" type="string" />
15+
</model>
16+
</h:head>
17+
<h:body>
18+
<input ref="/data/name">
19+
<label>What is the name?</label>
20+
</input>
21+
</h:body>
22+
</h:html>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"duplicate_check": {
3+
"test": "This property is not supposed to be consumed for this form type"
4+
}
5+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0"?>
2+
<h:html xmlns="http://www.w3.org/2002/xforms" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:jr="http://openrosa.org/javarosa" xmlns:orx="http://openrosa.org/xforms/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
3+
<h:head>
4+
<h:title>Merge properties</h:title>
5+
<model>
6+
<instance>
7+
<data id="example" version="2015-06-05">
8+
<name/>
9+
</data>
10+
<meta>
11+
<instanceID/>
12+
</meta>
13+
</instance>
14+
<bind nodeset="/data/name" type="string" />
15+
</model>
16+
</h:head>
17+
<h:body>
18+
<input ref="/data/name">
19+
<label>What is the name?</label>
20+
</input>
21+
</h:body>
22+
</h:html>

test/lib/upload-forms.spec.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,42 @@ describe('upload-forms', () => {
7979
});
8080
});
8181

82+
it('should consume "duplicate_check" property for contact', async () => {
83+
sinon.stub(environment, 'isArchiveMode').get(() => false);
84+
sinon.stub(environment, 'pathToProject').get(() => '.');
85+
sinon.stub(Date, 'now').returns(123123);
86+
return uploadForms.__with__({ validateForms })(async () => {
87+
const logInfo = sinon.stub(log, 'info');
88+
const logWarn = sinon.stub(log, 'warn');
89+
await uploadForms.execute(`${BASE_DIR}/duplicate_check-properties`, 'contact');
90+
expect(logInfo.args[0][0]).to.equal('Preparing form for upload: example.xml…');
91+
expect(logWarn.callCount).to.equal(0);
92+
const form = await api.db.get('form:example');
93+
expect(form.duplicate_check).to.deep.equal({
94+
'expression': 'levenshteinEq(current.name, existing.name, 3) && ageInYears(current) === ageInYears(existing)',
95+
'disabled': true
96+
});
97+
});
98+
});
99+
100+
it('should ignore "duplicate_check" property for report', async () => {
101+
sinon.stub(environment, 'isArchiveMode').get(() => false);
102+
sinon.stub(environment, 'pathToProject').get(() => '.');
103+
sinon.stub(Date, 'now').returns(123123);
104+
return uploadForms.__with__({ validateForms })(async () => {
105+
const logInfo = sinon.stub(log, 'info');
106+
const logWarn = sinon.stub(log, 'warn');
107+
await uploadForms.execute(`${BASE_DIR}/duplicate_check-properties`, 'report');
108+
expect(logInfo.args[0][0]).to.equal('Preparing form for upload: example.xml…');
109+
expect(logWarn.callCount).to.equal(1);
110+
const form = await api.db.get('form:example');
111+
expect(form.duplicate_check).to.deep.equal(undefined);
112+
expect(logWarn.args[0][0]).to.equal(
113+
'Ignoring unknown properties in '+
114+
'data/lib/upload-forms/duplicate_check-properties/forms/report/example.properties.json: '+
115+
'duplicate_check'
116+
);
117+
});
118+
});
119+
82120
});

0 commit comments

Comments
 (0)