diff --git a/lib/model/query/forms.js b/lib/model/query/forms.js index 73b6f4d60..c75fe6440 100644 --- a/lib/model/query/forms.js +++ b/lib/model/query/forms.js @@ -75,6 +75,9 @@ const createNew = (partial, project, publish = false) => async ({ run, Datasets, (partial.aux.key.isDefined() ? resolve(Option.none()) : getDataset(partial.xml)) // Don't parse dataset schema if Form has encryption key ]); + // Check that meta field (group containing instanceId and name) exists + await Forms.checkMeta(fields); + // Check for xmlFormId collisions with previously deleted forms await Forms.checkDeletedForms(partial.xmlFormId, project.id); await Forms.rejectIfWarnings(); @@ -617,6 +620,13 @@ order by actors."displayName" asc`) //////////////////////////////////////////////////////////////////////////////// // CHECKING CONSTRAINTS, STRUCTURAL CHANGES, ETC. +// This will check if a form contains a meta group (for capturing instanceID). +// It is only to be used for newly uploaded forms. +const checkMeta = (fields) => () => + (fields.some((f) => (f.name === 'meta' && f.type === 'structure')) + ? resolve() + : reject(Problem.user.missingMeta())); + const checkDeletedForms = (xmlFormId, projectId) => ({ maybeOne, context }) => (context.query.ignoreWarnings ? resolve() : maybeOne(sql`SELECT 1 FROM forms WHERE "xmlFormId" = ${xmlFormId} AND "projectId" = ${projectId} AND "deletedAt" IS NOT NULL LIMIT 1`) .then(deletedForm => { if (deletedForm.isDefined()) { @@ -681,7 +691,7 @@ module.exports = { getByProjectId, getByProjectAndXmlFormId, getByProjectAndNumericId, getAllByAuth, getFields, getBinaryFields, getStructuralFields, getMergedFields, - rejectIfWarnings, checkDeletedForms, checkStructuralChange, checkFieldDowncast, + rejectIfWarnings, checkMeta, checkDeletedForms, checkStructuralChange, checkFieldDowncast, _newSchema, lockDefs, getAllSubmitters }; diff --git a/lib/util/problem.js b/lib/util/problem.js index ec9391deb..5948072dc 100644 --- a/lib/util/problem.js +++ b/lib/util/problem.js @@ -108,6 +108,9 @@ const problems = { // problem parsing the entity form datasetLinkNotAllowed: problem(400.26, () => 'Dataset can only be linked to attachments with "Data File" type.'), + // meta group in form definition is missing + missingMeta: problem(400.27, () => 'The form does not contain a \'meta\' group.'), + // no detail information for security reasons. authenticationFailed: problem(401.2, () => 'Could not authenticate with the provided credentials.'), diff --git a/test/data/xml.js b/test/data/xml.js index 4df69c23a..e9afbd8fc 100644 --- a/test/data/xml.js +++ b/test/data/xml.js @@ -173,11 +173,15 @@ module.exports = { + + + + @@ -202,10 +206,14 @@ module.exports = { + + + + @@ -316,10 +324,14 @@ module.exports = { + + + + diff --git a/test/integration/api/forms/draft.js b/test/integration/api/forms/draft.js index 4a880516d..1185bd005 100644 --- a/test/integration/api/forms/draft.js +++ b/test/integration/api/forms/draft.js @@ -406,6 +406,35 @@ describe('api: /projects/:id/forms (drafts)', () => { .set('Content-Type', 'application/xml') .expect(200))))); + + it('should allow new draft with missing meta group', testService(async (service) => { + // This case is not expected, but it mimics a different scenario where there are + // already meta-less forms in a user's central repo and they need to be able to update them + // without breaking their workflows. + const asAlice = await service.login('alice'); + + const simpleMissingMeta = ` + + Simple + + + + + + + + + + + + `; + + await asAlice.post('/v1/projects/1/forms/simple/draft?ignoreWarnings=true') + .send(simpleMissingMeta) + .set('Content-Type', 'application/xml') + .expect(200); + })); + it('should identify attachments', testService((service) => service.login('alice', (asAlice) => asAlice.post('/v1/projects/1/forms/simple/draft?ignoreWarnings=true') diff --git a/test/integration/api/forms/forms.js b/test/integration/api/forms/forms.js index 5376c7400..224f7fe90 100644 --- a/test/integration/api/forms/forms.js +++ b/test/integration/api/forms/forms.js @@ -438,6 +438,59 @@ describe('api: /projects/:id/forms (create, read, update)', () => { }); })); + it('should reject form with missing meta group', testService(async (service) => { + const asAlice = await service.login('alice'); + + const missingMeta = ` + + Missing Meta + + + + + + + + + + + + + `; + + await asAlice.post('/v1/projects/1/forms') + .send(missingMeta) + .set('Content-Type', 'application/xml') + .expect(400); + })); + + it('should reject form with meta field that is not a group', testService(async (service) => { + const asAlice = await service.login('alice'); + + const missingMeta = ` + + Non Group Meta + + + + + + + + + + + + + + `; + + await asAlice.post('/v1/projects/1/forms') + .send(missingMeta) + .set('Content-Type', 'application/xml') + .expect(400); + })); + it('should create the form for xml files with warnings given ignoreWarnings', testService(async (service) => { const asAlice = await service.login('alice', identity); @@ -809,6 +862,8 @@ describe('api: /projects/:id/forms (create, read, update)', () => { .expect(200) .then(({ body }) => { body.should.eql([ + { name: 'meta', path: '/meta', type: 'structure', binary: null, selectMultiple: null }, + { name: 'instanceID', path: '/meta/instanceID', type: 'string', binary: null, selectMultiple: null }, { name: 'q1', path: '/q1', type: 'string', binary: null, selectMultiple: true }, { name: 'g1', path: '/g1', type: 'structure', binary: null, selectMultiple: null }, { name: 'q2', path: '/g1/q2', type: 'string', binary: null, selectMultiple: true } @@ -821,13 +876,16 @@ describe('api: /projects/:id/forms (create, read, update)', () => { + + + <17/> <4.2/> - + @@ -850,6 +908,8 @@ describe('api: /projects/:id/forms (create, read, update)', () => { .expect(200) .then(({ body }) => { body.should.eql([ + { name: 'meta', path: '/meta', type: 'structure', binary: null, selectMultiple: null }, + { name: 'instanceID', path: '/meta/instanceID', type: 'string', binary: null, selectMultiple: null }, { name: 'q1_8', path: '/q1_8', type: 'structure', binary: null, selectMultiple: null }, { name: '_17', path: '/q1_8/_17', type: 'string', binary: null, selectMultiple: null }, { name: '_4_2', path: '/_4_2', type: 'number', binary: null, selectMultiple: null } diff --git a/test/integration/api/forms/list.js b/test/integration/api/forms/list.js index 68288719a..200701517 100644 --- a/test/integration/api/forms/list.js +++ b/test/integration/api/forms/list.js @@ -328,7 +328,7 @@ describe('api: /projects/:id/forms (listing forms)', () => { withAttachments withAttachments - md5:7eb21b5b123b0badcf2b8f50bcf1cbd0 + md5:dda89055c8fec222458f702aead30a83 ${domain}/v1/projects/1/forms/withAttachments.xml ${domain}/v1/projects/1/forms/withAttachments/manifest diff --git a/test/integration/api/forms/test.js b/test/integration/api/forms/test.js index 1771d1d16..9cbbc35e2 100644 --- a/test/integration/api/forms/test.js +++ b/test/integration/api/forms/test.js @@ -120,7 +120,7 @@ describe('api: /projects/:id/forms (testing drafts)', () => { withAttachments withAttachments - md5:7eb21b5b123b0badcf2b8f50bcf1cbd0 + md5:dda89055c8fec222458f702aead30a83 ${domain}/v1/test/${token}/projects/1/forms/withAttachments/draft.xml ${domain}/v1/test/${token}/projects/1/forms/withAttachments/draft/manifest diff --git a/test/integration/api/submissions.js b/test/integration/api/submissions.js index 1adea0552..38532890b 100644 --- a/test/integration/api/submissions.js +++ b/test/integration/api/submissions.js @@ -1575,11 +1575,11 @@ describe('api: /forms/:id/submissions', () => { .then((result) => { result.filenames.should.containDeep([ 'selectMultiple.csv' ]); const lines = result['selectMultiple.csv'].split('\n'); - lines[0].should.equal('SubmissionDate,q1,q1/a,q1/b,g1-q2,g1-q2/m,g1-q2/x,g1-q2/y,g1-q2/z,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion'); + lines[0].should.equal('SubmissionDate,meta-instanceID,q1,q1/a,q1/b,g1-q2,g1-q2/m,g1-q2/x,g1-q2/y,g1-q2/z,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion'); lines[1].slice('yyyy-mm-ddThh:mm:ss._msZ'.length) - .should.equal(',b,0,1,m x,1,1,0,0,two,5,Alice,0,0,,,,0,'); + .should.equal(',two,b,0,1,m x,1,1,0,0,two,5,Alice,0,0,,,,0,'); lines[2].slice('yyyy-mm-ddThh:mm:ss._msZ'.length) - .should.equal(',a b,1,1,x y z,0,1,1,1,one,5,Alice,0,0,,,,0,'); + .should.equal(',one,a b,1,1,x y z,0,1,1,1,one,5,Alice,0,0,,,,0,'); }))))); it('should omit multiples it does not know about', testService((service) => @@ -1597,11 +1597,11 @@ describe('api: /forms/:id/submissions', () => { .then((result) => { result.filenames.should.containDeep([ 'selectMultiple.csv' ]); const lines = result['selectMultiple.csv'].split('\n'); - lines[0].should.equal('SubmissionDate,q1,g1-q2,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion'); + lines[0].should.equal('SubmissionDate,meta-instanceID,q1,g1-q2,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion'); lines[1].slice('yyyy-mm-ddThh:mm:ss._msZ'.length) - .should.equal(',b,m x,two,5,Alice,0,0,,,,0,'); + .should.equal(',two,b,m x,two,5,Alice,0,0,,,,0,'); lines[2].slice('yyyy-mm-ddThh:mm:ss._msZ'.length) - .should.equal(',a b,x y z,one,5,Alice,0,0,,,,0,'); + .should.equal(',one,a b,x y z,one,5,Alice,0,0,,,,0,'); }))))); it('should split select multiples and filter given both options', testService((service, container) => @@ -1741,11 +1741,11 @@ describe('api: /forms/:id/submissions', () => { .then((result) => { result.filenames.should.containDeep([ 'selectMultiple.csv' ]); const lines = result['selectMultiple.csv'].split('\n'); - lines[0].should.equal('SubmissionDate,q1,q1/a,q1/b,q2,q2/m,q2/x,q2/y,q2/z,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion'); + lines[0].should.equal('SubmissionDate,instanceID,q1,q1/a,q1/b,q2,q2/m,q2/x,q2/y,q2/z,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion'); lines[1].slice('yyyy-mm-ddThh:mm:ss._msZ'.length) - .should.equal(',b,0,1,m x,1,1,0,0,two,5,Alice,0,0,,,,0,'); + .should.equal(',two,b,0,1,m x,1,1,0,0,two,5,Alice,0,0,,,,0,'); lines[2].slice('yyyy-mm-ddThh:mm:ss._msZ'.length) - .should.equal(',a b,1,1,x y z,0,1,1,1,one,5,Alice,0,0,,,,0,'); + .should.equal(',one,a b,1,1,x y z,0,1,1,1,one,5,Alice,0,0,,,,0,'); }))))); it('should properly count present attachments', testService((service) => @@ -2186,11 +2186,11 @@ one,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff // eslint-disable-next-line no-multi-spaces .then(({ text }) => { const lines = text.split('\n'); - lines[0].should.equal('SubmissionDate,q1,q1/a,q1/b,g1-q2,g1-q2/m,g1-q2/x,g1-q2/y,g1-q2/z,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion'); + lines[0].should.equal('SubmissionDate,meta-instanceID,q1,q1/a,q1/b,g1-q2,g1-q2/m,g1-q2/x,g1-q2/y,g1-q2/z,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion'); lines[1].slice('yyyy-mm-ddThh:mm:ss._msZ'.length) - .should.equal(',b,0,1,m x,1,1,0,0,two,5,Alice,0,0,,,,0,'); + .should.equal(',two,b,0,1,m x,1,1,0,0,two,5,Alice,0,0,,,,0,'); lines[2].slice('yyyy-mm-ddThh:mm:ss._msZ'.length) - .should.equal(',a b,1,1,x y z,0,1,1,1,one,5,Alice,0,0,,,,0,'); + .should.equal(',one,a b,1,1,x y z,0,1,1,1,one,5,Alice,0,0,,,,0,'); }))))); it('should omit group paths if ?groupPaths=false is given', testService((service) => @@ -2279,11 +2279,13 @@ one,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff + + @@ -2323,13 +2325,13 @@ one,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff .expect(200) .then(({ text }) => { const lines = text.split('\n'); - lines[0].should.equal('SubmissionDate,q1,q1/a,q1/b,g1-q2,g1-q2/m,g1-q2/x,g1-q2/y,g1-q2/z,q3,q3/z,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion'); + lines[0].should.equal('SubmissionDate,meta-instanceID,q1,q1/a,q1/b,g1-q2,g1-q2/m,g1-q2/x,g1-q2/y,g1-q2/z,q3,q3/z,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion'); lines[1].slice('yyyy-mm-ddThh:mm:ss._msZ'.length) - .should.equal(',a b,1,1,m,1,0,0,0,z,1,three,5,Alice,0,0,,,,0,3'); + .should.equal(',three,a b,1,1,m,1,0,0,0,z,1,three,5,Alice,0,0,,,,0,3'); lines[2].slice('yyyy-mm-ddThh:mm:ss._msZ'.length) - .should.equal(',b,0,1,m x,1,1,0,0,,0,two,5,Alice,0,0,,,,0,'); + .should.equal(',two,b,0,1,m x,1,1,0,0,,0,two,5,Alice,0,0,,,,0,'); lines[3].slice('yyyy-mm-ddThh:mm:ss._msZ'.length) - .should.equal(',a b,1,1,x y z,0,1,1,1,,0,one,5,Alice,0,0,,,,0,'); + .should.equal(',one,a b,1,1,x y z,0,1,1,1,,0,one,5,Alice,0,0,,,,0,'); }))))); }); }); @@ -2471,11 +2473,11 @@ one,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff .then((result) => { result.filenames.should.containDeep([ 'selectMultiple.csv' ]); const lines = result['selectMultiple.csv'].split('\n'); - lines[0].should.equal('SubmissionDate,q1,q1/a,q1/b,g1-q2,g1-q2/m,g1-q2/x,g1-q2/y,g1-q2/z,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion'); + lines[0].should.equal('SubmissionDate,meta-instanceID,q1,q1/a,q1/b,g1-q2,g1-q2/m,g1-q2/x,g1-q2/y,g1-q2/z,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion'); lines[1].slice('yyyy-mm-ddThh:mm:ss._msZ'.length) - .should.equal(',b,0,1,m x,1,1,0,0,two,,,0,0,,,,0,'); + .should.equal(',two,b,0,1,m x,1,1,0,0,two,,,0,0,,,,0,'); lines[2].slice('yyyy-mm-ddThh:mm:ss._msZ'.length) - .should.equal(',a b,1,1,x y z,0,1,1,1,one,,,0,0,,,,0,'); + .should.equal(',one,a b,1,1,x y z,0,1,1,1,one,,,0,0,,,,0,'); }))))); }); diff --git a/test/integration/other/select-many.js b/test/integration/other/select-many.js index 5c31ea232..c8cd10783 100644 --- a/test/integration/other/select-many.js +++ b/test/integration/other/select-many.js @@ -94,10 +94,12 @@ describe('select many value processing', () => { + + @@ -143,11 +145,11 @@ describe('select many value processing', () => { .expect(200) .then(({ text }) => { const lines = text.split('\n'); - lines[0].should.equal('SubmissionDate,q1,q1/a,q1/b,g1-q2,g1-q2/x,g1-q2/y,g1-q2/z,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion'); + lines[0].should.equal('SubmissionDate,meta-instanceID,q1,q1/a,q1/b,g1-q2,g1-q2/x,g1-q2/y,g1-q2/z,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion'); lines[1].slice('yyyy-mm-ddThh:mm:ss._msZ'.length) - .should.equal(',a b,1,1,x y z,1,1,1,one,5,Alice,0,0,,,,0,2'); + .should.equal(',one,a b,1,1,x y z,1,1,1,one,5,Alice,0,0,,,,0,2'); lines[2].slice('yyyy-mm-ddThh:mm:ss._msZ'.length) - .should.equal(',b,0,1,x,1,0,0,two,5,Alice,0,0,,,,0,'); + .should.equal(',two,b,0,1,x,1,0,0,two,5,Alice,0,0,,,,0,'); }); })); }); diff --git a/test/unit/data/briefcase.js b/test/unit/data/briefcase.js index 7ac3e5061..c3c98f481 100644 --- a/test/unit/data/briefcase.js +++ b/test/unit/data/briefcase.js @@ -21,7 +21,7 @@ const instance = (id, data, formVersion = 'version') => ({ instanceId: id, createdAt: new Date('2018-01-01T00:00:00Z'), def: {}, - xml: `${data}`, + xml: `${id}${data}`, aux: { attachment: { present: 0, expected: 0 }, encryption: {}, edit: { count: 0 }, exports: { formVersion } } }); @@ -417,9 +417,9 @@ describe('.csv.zip briefcase output @slow', () => { result.filenames.should.eql([ 'selectMultiple.csv' ]); result['selectMultiple.csv'].should.equal( - `SubmissionDate,q1,q1/x,q1/y,q1/z,g1-q2,g1-q2/m,g1-q2/n,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion -2018-01-01T00:00:00.000Z,a b,0,0,0,x y z,0,0,one,,,0,0,,,,0,version -2018-01-01T00:00:00.000Z,b,0,0,0,m x,1,0,two,,,0,0,,,,0,version + `SubmissionDate,meta-instanceID,q1,q1/x,q1/y,q1/z,g1-q2,g1-q2/m,g1-q2/n,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion +2018-01-01T00:00:00.000Z,one,a b,0,0,0,x y z,0,0,one,,,0,0,,,,0,version +2018-01-01T00:00:00.000Z,two,b,0,0,0,m x,1,0,two,,,0,0,,,,0,version `); // eslint-disable-line function-paren-newline done(); }); @@ -457,9 +457,9 @@ describe('.csv.zip briefcase output @slow', () => { `; const inStream = streamTest.fromObjects([ - instance('one', 'oneAliceApartment
101 Pike StSeattle, WA
'), - instance('two', 'twoBob
20 BroadwayPortland, OR
Condo
'), - instance('three', 'threeChelseaHouse
San Francisco, CA99 Mission Ave
'), + instance('one', 'AliceApartment
101 Pike StSeattle, WA
'), + instance('two', 'Bob
20 BroadwayPortland, OR
Condo
'), + instance('three', 'ChelseaHouse
San Francisco, CA99 Mission Ave
'), ]); callAndParse(inStream, formXml, 'structuredform', (err, result) => { @@ -508,9 +508,9 @@ describe('.csv.zip briefcase output @slow', () => { `; const inStream = streamTest.fromObjects([ - instance('one', 'oneAliceApartment
101 Pike StSeattle, WA
'), - instance('two', 'twoBob
20 BroadwayPortland, OR
Condo
'), - instance('three', 'threeChelseaHouse
San Francisco, CA99 Mission Ave
'), + instance('one', 'AliceApartment
101 Pike StSeattle, WA
'), + instance('two', 'Bob
20 BroadwayPortland, OR
Condo
'), + instance('three', 'ChelseaHouse
San Francisco, CA99 Mission Ave
'), ]); fieldsFor(formXml).then((fields) => { @@ -543,9 +543,9 @@ describe('.csv.zip briefcase output @slow', () => { result.filenames.should.eql([ 'selectMultiple.csv' ]); result['selectMultiple.csv'].should.equal( - `SubmissionDate,q1,q1/x,q1/y,q1/z,q2,q2/m,q2/n,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion -2018-01-01T00:00:00.000Z,a b,0,0,0,x y z,0,0,one,,,0,0,,,,0,version -2018-01-01T00:00:00.000Z,b,0,0,0,m x,1,0,two,,,0,0,,,,0,version + `SubmissionDate,instanceID,q1,q1/x,q1/y,q1/z,q2,q2/m,q2/n,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion +2018-01-01T00:00:00.000Z,one,a b,0,0,0,x y z,0,0,one,,,0,0,,,,0,version +2018-01-01T00:00:00.000Z,two,b,0,0,0,m x,1,0,two,,,0,0,,,,0,version `); // eslint-disable-line function-paren-newline done(); }); @@ -602,9 +602,9 @@ describe('.csv.zip briefcase output @slow', () => { `; const inStream = streamTest.fromObjects([ - instance('one', 'oneAlice30'), - instance('two', 'twoBob34Billy4Blaine6'), - instance('three', 'threeChelsea38Candace2'), + instance('one', 'Alice30'), + instance('two', 'Bob34Billy4Blaine6'), + instance('three', 'Chelsea38Candace2'), ]); callAndParse(inStream, formXml, 'singlerepeat', (err, result) => { @@ -745,9 +745,9 @@ Candace,2,three,three/children/child[1] `; const inStream = streamTest.fromObjects([ - instance('one', 'oneAlice30'), - instance('two', 'twoBob34Billy4R2-D2Blaine6BB-8Porg plushieBaker7'), - instance('three', 'threeChelsea38CandaceMillennium FalconX-WingPod racer2'), + instance('one', 'Alice30'), + instance('two', 'Bob34Billy4R2-D2Blaine6BB-8Porg plushieBaker7'), + instance('three', 'Chelsea38CandaceMillennium FalconX-WingPod racer2'), ]); callAndParse(inStream, formXml, 'multirepeat', (err, result) => { @@ -1119,9 +1119,9 @@ some text 3.1.4,uuid:0a1b861f-a5fd-4f49-846a-78dcf06cfc1b/g1[3]/g2[1],uuid:0a1b8 `; const inStream = streamTest.fromObjects([ - instance('one', 'oneAlice'), - instance('two', 'twoBobBobs HardwareLocal CoffeeNasrin'), - instance('three', 'threeChelseaInstantaneous FoodFerrenceMick'), + instance('one', 'Alice'), + instance('two', 'BobBobs HardwareLocal CoffeeNasrin'), + instance('three', 'ChelseaInstantaneous FoodFerrenceMick'), ]); callAndParse(inStream, formXml, 'ambiguous', (err, result) => {