Skip to content

Commit

Permalink
Fix bug in forms missing <inputs> section
Browse files Browse the repository at this point in the history
Previously, if forms did not have an <inputs> element, the main form data would
be removed from the XML.
  • Loading branch information
alxndrsn committed Aug 22, 2017
1 parent bd938dd commit d80f88d
Show file tree
Hide file tree
Showing 11 changed files with 310 additions and 62 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
{
"name": "medic-configurer-beta",
"version": "1.2.1",
"version": "1.3.0",
"description": "Configure Medic Mobile deployments",
"main": "index.js",
"scripts": {
"clean": "rm -rf ./build/",
"jshint": "jshint src/**/*.js bin/*.js test/**/*.js",
"test": "npm run jshint && mocha test/**/*.spec.js"
"test": "npm run jshint && npm run clean && mocha test/**/*.spec.js"
},
"bin": {
"medic-conf": "bin/medic-conf.js",
Expand Down
16 changes: 9 additions & 7 deletions src/lib/convert-forms.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,17 @@ const shiftThingsAroundInTheModel = (path, xml) => {
const baseName = fs.path.parse(path).name.replace(/-(create|edit)$/, '');
let matchedBlock;

const matcher = new RegExp(`\\s*<${baseName}>[\\s\\S]*</${baseName}>\\s*(\\r|\\n)`);
if(xml.includes('</inputs>')) {
const matcher = new RegExp(`\\s*<${baseName}>[\\s\\S]*</${baseName}>\\s*(\\r|\\n)`);

xml = xml.replace(matcher, match => {
matchedBlock = match;
return '\n';
});
xml = xml.replace(matcher, match => {
matchedBlock = match;
return '\n';
});

if(matchedBlock) {
xml = xml.replace(/<\/inputs>(\r|\n)/, '</inputs>' + matchedBlock);
if(matchedBlock) {
xml = xml.replace(/<\/inputs>(\r|\n)/, '</inputs>' + matchedBlock);
}
}

return xml;
Expand Down
2 changes: 1 addition & 1 deletion test/.jshintrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"extends": "../.jshintrc",
"predef": [ "beforeEach", "describe", "it" ]
"predef": [ "before", "beforeEach", "describe", "it" ]
}
Binary file not shown.
80 changes: 80 additions & 0 deletions test/data/fn/convert-contact-forms/person-edit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?xml version="1.0"?>
<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">
<h:head>
<h:title>Edit Person</h:title>
<model>
<instance>
<data delimiter="#" id="person" prefix="J1!person!" version="2016-04-06">
<person>
<type>person</type>
<parent/>
<name/>
<date_of_birth/>
<date_of_birth_method/>
<sex/>
<notes/>
<phone/>
<alternate_phone/>
</person>
<meta>
<instanceID/>
</meta>
</data>
</instance>
<bind nodeset="/data/person/type" type="string"/>
<bind nodeset="/data/person/parent" type="string"/>
<bind nodeset="/data/person/name" required="true()" type="string"/>
<bind nodeset="/data/person/date_of_birth" type="date"/>
<bind nodeset="/data/person/date_of_birth_method" type="select1"/>
<bind nodeset="/data/person/sex" type="select1"/>
<bind nodeset="/data/person/notes" type="string"/>
<bind nodeset="/data/person/phone" type="tel"/>
<bind nodeset="/data/person/alternate_phone" type="tel"/>
<bind calculate="concat('uuid:', uuid())" nodeset="/data/meta/instanceID" readonly="true()" type="string"/>
</model>
</h:head>
<h:body>
<group ref="/data/person">
<input appearance="hidden" ref="/data/person/type">
<label>Person Type</label>
<hint>mandatory</hint>
</input>
<input appearance="db-object bind-id-only hidden" ref="/data/person/parent">
<label>Parent</label>
</input>
<input ref="/data/person/name">
<label>Names</label>
</input>
<input ref="/data/person/date_of_birth">
<label>Date of Birth</label>
</input>
<select1 appearance="hidden" ref="/data/person/date_of_birth_method">
<label>Method to select date of birth</label>
<item>
<label>Date unknown</label>
<value>approx</value>
</item>
</select1>
<select1 appearance="horizontal" ref="/data/person/sex">
<label>Gender</label>
<item>
<label>Female</label>
<value>female</value>
</item>
<item>
<label>Male</label>
<value>male</value>
</item>
</select1>
<input ref="/data/person/notes">
<label>Notes (optional)</label>
</input>
<input appearance="numbers" ref="/data/person/phone">
<label>Primary Mobile Number</label>
</input>
<input appearance="numbers" ref="/data/person/alternate_phone">
<label>Secondary Mobile Number</label>
</input>
</group>
</h:body>
</h:html>
Binary file added test/data/fn/convert-contact-forms/person.xlsx
Binary file not shown.
131 changes: 131 additions & 0 deletions test/data/fn/convert-contact-forms/person.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<?xml version="1.0"?>
<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">
<h:head>
<h:title>Add Person</h:title>
<model>
<instance>
<data delimiter="#" id="person" prefix="J1!person!" version="2017-08-16 00:00:00">
<inputs>
<meta>
<location>
<lat/>
<long/>
<error/>
<message/>
</location>
</meta>
<user>
<facility_id/>
</user>
</inputs>
<person>
<type>person</type>
<parent>PARENT</parent>
<name/>
<external_id/>
<nationality/>
<nationality_other/>
<contact_telephone_number/>
<date_of_birth/>
<sex/>
<geolocation/>
</person>
<meta>
<instanceID/>
</meta>
</data>
</instance>
<bind nodeset="/data/inputs" relevant="0"/>
<bind nodeset="/data/inputs/user/facility_id" type="string"/>
<bind nodeset="/data/person/type" type="string"/>
<bind nodeset="/data/person/parent" type="string"/>
<bind nodeset="/data/person/name" required="true()" type="string"/>
<bind nodeset="/data/person/external_id" required="false()" type="string"/>
<bind nodeset="/data/person/nationality" required="true()" type="select1"/>
<bind nodeset="/data/person/nationality_other" relevant="selected( /data/person/nationality , 'other')" type="string"/>
<bind nodeset="/data/person/contact_telephone_number" type="string"/>
<bind nodeset="/data/person/date_of_birth" required="true()" type="date"/>
<bind nodeset="/data/person/sex" required="true()" type="select1"/>
<bind calculate="concat(../../inputs/meta/location/lat, concat(' ', ../../inputs/meta/location/long))" nodeset="/data/person/geolocation" type="string"/>
<bind calculate="concat('uuid:', uuid())" nodeset="/data/meta/instanceID" readonly="true()" type="string"/>
</model>
</h:head>
<h:body>
<group ref="/data/inputs">
<group ref="/data/inputs/user">
<label>User</label>
<input ref="/data/inputs/user/facility_id">
<label>Facility ID for the parent user</label>
</input>
</group>
</group>
<group ref="/data/person">
<label>Person</label>
<input appearance="hidden" ref="/data/person/type">
<label>Person Type</label>
<hint>mandatory</hint>
</input>
<input appearance="hidden" ref="/data/person/parent">
<label>Parent</label>
<hint>mandatory</hint>
</input>
<input ref="/data/person/name">
<label>Names</label>
</input>
<input ref="/data/person/external_id">
<label>New Client's Unique Code</label>
</input>
<select1 appearance="minimal" ref="/data/person/nationality">
<label>Nationality</label>
<item>
<label>Kenyan</label>
<value>kenyan</value>
</item>
<item>
<label>Ugandan</label>
<value>ugandan</value>
</item>
<item>
<label>Rwandese</label>
<value>rwandese</value>
</item>
<item>
<label>Tanzanian</label>
<value>tanzanian</value>
</item>
<item>
<label>Burundian</label>
<value>burundian</value>
</item>
<item>
<label>Congolese</label>
<value>congolese</value>
</item>
<item>
<label>Other</label>
<value>other</value>
</item>
</select1>
<input ref="/data/person/nationality_other">
<label>Specify other</label>
</input>
<input ref="/data/person/contact_telephone_number">
<label>Contact Telephone Number</label>
</input>
<input ref="/data/person/date_of_birth">
<label>Date of Birth</label>
</input>
<select1 appearance="horizontal-compact" ref="/data/person/sex">
<label>Sex</label>
<item>
<label>Male</label>
<value>male</value>
</item>
<item>
<label>Female</label>
<value>female</value>
</item>
</select1>
</group>
</h:body>
</h:html>
53 changes: 1 addition & 52 deletions test/fn/convert-app-forms.spec.js
Original file line number Diff line number Diff line change
@@ -1,52 +1 @@
const assert = require('chai').assert;
const fs = require('../../src/lib/sync-fs');
const path = require('path');
const warn = require('../../src/lib/log').warn;

const convertAppForms = require('../../src/fn/convert-app-forms');

const PROPERTIES_JSON = /\.properties.json/;
const XLS = /\.xlsx$/;
const XML = /\.xml$/;

describe('convert-app-forms', () => {
let projectDir;
let testId = 0;

beforeEach(() => {
// recursively copy forms and expected XML to temp directory
const srcDir = 'test/data/fn/convert-app-forms';
projectDir = 'build/test/' + (++testId);
const appFormsDir = `${projectDir}/forms/app`;

fs.mkdir(appFormsDir);

fs.recurseFiles(srcDir)
.forEach(file => {
let targetName = path.basename(file);

if(XML.test(file)) targetName += '.expected';
else if(!XLS.test(file) && !PROPERTIES_JSON.test(file))
warn(`Ignoring unexpected file type: ${file}`);

fs.copy(file, `${appFormsDir}/${targetName}`);
});
});

it('should convert app forms in-line with examples', function() {
// given
this.timeout(30000);

// when
return convertAppForms(projectDir)

// then
.then(() => fs.recurseFiles(`${projectDir}/forms/app`)
.filter(name => XML.test(name))
.forEach(xml => {
const expectedXml = `${xml}.expected`;
assert.ok(fs.exists(expectedXml), `Missing expected XML file: ${xml}`);
assert.equal(fs.read(xml), fs.read(expectedXml), `Content of ${xml} was not as expected.`);
}));
});
});
require('./convert-forms.utils.js').testFor('app');
1 change: 1 addition & 0 deletions test/fn/convert-contact-forms.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require('./convert-forms.utils.js').testFor('contact');
59 changes: 59 additions & 0 deletions test/fn/convert-forms.utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
const assert = require('chai').assert;
const fs = require('../../src/lib/sync-fs');
const path = require('path');
const warn = require('../../src/lib/log').warn;

const PROPERTIES_JSON = /\.properties.json/;
const XLS = /\.xlsx$/;
const XML = /\.xml$/;


module.exports = {
testFor: type => {

const convertForms = require(`../../src/fn/convert-${type}-forms`);

describe(`convert-${type}-forms`, function() {

this.timeout(30000); // allow time for form conversion

const projectDir = 'build/test';

// recursively copy forms and expected XML to temp directory
const srcDir = `test/data/fn/convert-${type}-forms`;
const formsDir = `${projectDir}/forms/${type}`;

fs.mkdir(formsDir);

fs.recurseFiles(srcDir)
.forEach(file => {
let targetName = path.basename(file);

if(XML.test(file)) targetName += '.expected';
else if(!XLS.test(file) && !PROPERTIES_JSON.test(file))
warn(`Ignoring unexpected file type: ${file}`);

fs.copy(file, `${formsDir}/${targetName}`);
});

convertForms(projectDir)
.then(() => {

fs.recurseFiles(formsDir)
.filter(name => XML.test(name))
.forEach(xml => {

it(`should convert ${xml} as expected`, () => {

const expectedXml = `${xml}.expected`;
assert.ok(fs.exists(expectedXml), `Missing expected XML file: ${xml}`);
assert.equal(fs.read(xml), fs.read(expectedXml), `Content of ${xml} was not as expected.`);

});
});
});

});

},
};
Loading

0 comments on commit d80f88d

Please sign in to comment.