diff --git a/test/integration/api/datasets.js b/test/integration/api/datasets.js
index 067dd4926..8f2b2ec73 100644
--- a/test/integration/api/datasets.js
+++ b/test/integration/api/datasets.js
@@ -2865,7 +2865,7 @@ describe('datasets and entities', () => {
});
}));
- // cb#551 issue, tag has no children
+ // c#551 issue, tag has no children
it('should allow update where no label or no properties are updated', testService(async (service, container) => {
const asAlice = await service.login('alice');
@@ -2930,7 +2930,7 @@ describe('datasets and entities', () => {
});
}));
- // cb#552 issue, can't add label to entity update form that previously didnt have label
+ // c#552 issue, can't add label to entity update form that previously didnt have label
it('should allow update where no label or no properties are updated', testService(async (service) => {
const asAlice = await service.login('alice');
@@ -2981,8 +2981,8 @@ describe('datasets and entities', () => {
.expect(200);
}));
- // cb#553 issue, forms with and without entity label show different fields
- // (because entity has type 'unknown' instead of 'structure')
+ // c#553 issue, forms with and without entity label show different fields
+ // (because entity was previously type 'unknown' instead of 'structure')
it('should allow update where no label or no properties are updated', testService(async (service) => {
const asAlice = await service.login('alice');
diff --git a/test/unit/data/dataset.js b/test/unit/data/dataset.js
index 81c5c95dd..32285cbce 100644
--- a/test/unit/data/dataset.js
+++ b/test/unit/data/dataset.js
@@ -211,7 +211,7 @@ describe('parsing dataset from entity block', () => {
should.not.exist(fields[2].propertyName);
}));
- it('should figure out type of entity block from form def', async () => {
+ it('should alawys parse entity field as type structure', async () => {
const form = (entityBlock) => `
@@ -229,72 +229,51 @@ describe('parsing dataset from entity block', () => {
`;
+ // Entity block has no children
const noChildEntity = '';
await getFormFields(form(noChildEntity)).then((fields) => {
- fields[0].name.should.equal('age');
- fields[0].path.should.equal('/age');
- fields[0].type.should.equal('int');
-
- fields[1].name.should.equal('meta');
- fields[1].path.should.equal('/meta');
- fields[1].type.should.equal('structure');
-
fields[2].name.should.equal('entity');
fields[2].path.should.equal('/meta/entity');
fields[2].type.should.equal('structure');
});
+ // Entity block has no children
const emptyEntity = '';
await getFormFields(form(emptyEntity)).then((fields) => {
- fields[0].name.should.equal('age');
- fields[0].path.should.equal('/age');
- fields[0].type.should.equal('int');
-
- fields[1].name.should.equal('meta');
- fields[1].path.should.equal('/meta');
- fields[1].type.should.equal('structure');
+ fields[2].name.should.equal('entity');
+ fields[2].path.should.equal('/meta/entity');
+ fields[2].type.should.equal('structure');
+ });
+ // Entity block has whitespace
+ const emptyEntityWhitespace = '';
+ await getFormFields(form(emptyEntityWhitespace)).then((fields) => {
fields[2].name.should.equal('entity');
fields[2].path.should.equal('/meta/entity');
fields[2].type.should.equal('structure');
});
+ // Entity block is not empty (most common case)
const nonEmptyEntity = '';
await getFormFields(form(nonEmptyEntity)).then((fields) => {
- fields[0].name.should.equal('age');
- fields[0].path.should.equal('/age');
- fields[0].type.should.equal('int');
-
- fields[1].name.should.equal('meta');
- fields[1].path.should.equal('/meta');
- fields[1].type.should.equal('structure');
-
fields[2].name.should.equal('entity');
fields[2].path.should.equal('/meta/entity');
- fields[2].type.should.equal('structure'); // is type structure because it contains a child
+ fields[2].type.should.equal('structure');
fields[3].name.should.equal('label');
fields[3].path.should.equal('/meta/entity/label');
- fields[3].type.should.equal('unknown'); // should possibly be something other than unknown (unknown bc no binding)
+ fields[3].type.should.equal('unknown'); // label is unknown because there is no child and no bind
});
- const nonEmptyLabel = '';
+ const nonEmptyLabel = '';
await getFormFields(form(nonEmptyLabel)).then((fields) => {
- fields[0].name.should.equal('age');
- fields[0].path.should.equal('/age');
- fields[0].type.should.equal('int');
-
- fields[1].name.should.equal('meta');
- fields[1].path.should.equal('/meta');
- fields[1].type.should.equal('structure');
-
fields[2].name.should.equal('entity');
fields[2].path.should.equal('/meta/entity');
fields[2].type.should.equal('structure'); // is type structure because it contains a child
fields[3].name.should.equal('label');
fields[3].path.should.equal('/meta/entity/label');
- fields[3].type.should.equal('unknown'); // should possibly be something other than unknown (unknown bc no children and no binding)
+ fields[3].type.should.equal('unknown'); // type unknown because no child node and no bind
});
});
});
diff --git a/test/unit/data/submission.js b/test/unit/data/submission.js
index f342aa8f6..986f8869b 100644
--- a/test/unit/data/submission.js
+++ b/test/unit/data/submission.js
@@ -66,9 +66,10 @@ describe('submission field streamer', () => {
should.config.checkProtoEql = true;
});
+ // true, false (entity has attributes and is included. other fields like /meta is structural but has no attributes so it is not included)
it('should include structural fields with attributes', (done) => {
fieldsFor(testData.forms.simpleEntity).then((fields) =>
- submissionXmlToFieldStream(fields, testData.instances.simpleEntity.one, true).pipe(toObjects((error, result) => {
+ submissionXmlToFieldStream(fields, testData.instances.simpleEntity.one, true, false).pipe(toObjects((error, result) => {
result.should.eql([
{ field: new MockField({ order: 4, name: 'entity', path: '/meta/entity', type: 'structure', attrs: {
create: '1',
@@ -84,9 +85,10 @@ describe('submission field streamer', () => {
})));
});
+ // false, false (entity has attributes but it is structural so not included)
it('should not include structural fields', (done) => {
fieldsFor(testData.forms.simpleEntity).then((fields) =>
- submissionXmlToFieldStream(fields, testData.instances.simpleEntity.one, false).pipe(toObjects((error, result) => {
+ submissionXmlToFieldStream(fields, testData.instances.simpleEntity.one, false, false).pipe(toObjects((error, result) => {
result.should.eql([
{ field: new MockField({ order: 5, name: 'label', path: '/meta/entity/label', type: 'unknown' }), text: 'Alice (88)' },
{ field: new MockField({ order: 0, name: 'name', path: '/name', type: 'string', propertyName: 'first_name' }), text: 'Alice' },
@@ -97,6 +99,7 @@ describe('submission field streamer', () => {
})));
});
+ // true, true (entity has attributes, age is empty)
it('should include structural elements with attributes and empty nodes', (done) => {
fieldsFor(testData.forms.simpleEntity).then((fields) =>
submissionXmlToFieldStream(fields, testData.instances.simpleEntity.one.replace('88', ''), true, true).pipe(toObjects((error, result) => {
@@ -115,57 +118,21 @@ describe('submission field streamer', () => {
})));
});
- it('should not return structural nodes when they have no attributes', async () => {
- const form = `
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- `;
-
- const fields = await fieldsFor(form);
- fields.length.should.equal(5);
-
- const sub = `
-
- one
- one
-
-
-
-
-
- 88
-
- `;
-
- await submissionXmlToFieldStream(fields, sub, true, true).pipe(toObjects((error, result) => {
- result.should.eql([
- // /meta/entity field is not present because it has no attribtues, which means it isn't used later by parseSubmissionXml
- // which is good, because it wont try to access non-existent entity attributes.
- // the entity system data stuff will be set to null and will log an appropriate error.
- { field: new MockField({ order: 4, name: 'label', path: '/meta/entity/label', type: 'unknown' }), text: 'foo' },
- // /person is also not included because it is a structural node with no attributes. but it's child is included.
- { field: new MockField({ order: 1, name: 'age', path: '/person/age', type: 'int', propertyName: 'age' }), text: '88' },
- ]);
- }));
+ // false, true (age is empty here. other fields like name and hometown are not empty and are returned as normal.)
+ it('should include empty nodes but no structural nodes', (done) => {
+ fieldsFor(testData.forms.simpleEntity).then((fields) =>
+ submissionXmlToFieldStream(fields, testData.instances.simpleEntity.one.replace('88', ''), false, true).pipe(toObjects((error, result) => {
+ result.should.eql([
+ { field: new MockField({ order: 5, name: 'label', path: '/meta/entity/label', type: 'unknown' }), text: 'Alice (88)' },
+ { field: new MockField({ order: 0, name: 'name', path: '/name', type: 'string', propertyName: 'first_name' }), text: 'Alice' },
+ { field: new MockField({ order: 1, name: 'age', path: '/age', type: 'int', propertyName: 'age' }), text: '' },
+ { field: new MockField({ order: 2, name: 'hometown', path: '/hometown', type: 'string' }), text: 'Chicago' }
+ ]);
+ done();
+ })));
});
+ // related to issue c#551 where block had no children so extracting the attributes was breaking.
it('should handle attributes on entity tag with no children', async () => {
const form = `
@@ -174,6 +141,9 @@ describe('submission field streamer', () => {
+
+
+
@@ -181,13 +151,15 @@ describe('submission field streamer', () => {
+ `;
+ // This is all the fields in the form including structural fields
const fields = await fieldsFor(form);
- fields.map(f => f.name).should.eql(['age', 'meta', 'entity']);
- fields.map(f => f.type).should.eql(['int', 'structure', 'structure']);
+ fields.map(f => f.name).should.eql(['age', 'location', 'hometown', 'meta', 'entity']);
+ fields.map(f => f.type).should.eql(['int', 'structure', 'string', 'structure', 'structure']);
const sub = `
@@ -196,17 +168,24 @@ describe('submission field streamer', () => {
88
+
+
+
`;
+ // This is where we use the full field list above to pull out only the fields that are relevant to entity parsing
+ // - with its attribuets
+ // - all leaf nodes even if they are empty
await submissionXmlToFieldStream(fields, sub, true, true).pipe(toObjects((error, result) => {
result.should.eql([
- { field: new MockField({ order: 2, name: 'entity', path: '/meta/entity', type: 'structure', attrs: {
+ { field: new MockField({ order: 4, name: 'entity', path: '/meta/entity', type: 'structure', attrs: {
update: '1',
baseVersion: '1',
dataset: 'people',
id: '12345678-1234-4123-8234-123456789abc'
} }), text: null },
{ field: new MockField({ order: 0, name: 'age', path: '/age', type: 'int', propertyName: 'age' }), text: '88' },
+ { field: new MockField({ order: 2, name: 'hometown', path: '/location/hometown', type: 'string', propertyName: 'hometown' }), text: '' },
]);
}));
});