Skip to content

Commit

Permalink
More test coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
ktuite committed Nov 13, 2023
1 parent c26d8f3 commit 0dcb9c2
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 36 deletions.
2 changes: 2 additions & 0 deletions lib/data/entity.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ const extractEntity = (body, propertyNames, existingEntity) => {
throw Problem.user.unexpectedValue({ field: 'label', value: '(empty string)', reason: 'Label cannot be blank.' });
else
entity.system.label = body.label;
else if (!existingEntity)
throw Problem.user.missingParameter({ field: 'label' });

if (body.data == null && body.label == null)
throw Problem.user.invalidEntity({ reason: 'No entity data or label provided.' });
Expand Down
109 changes: 105 additions & 4 deletions test/integration/api/entities.js
Original file line number Diff line number Diff line change
Expand Up @@ -1130,8 +1130,7 @@ describe('Entities API', () => {
});
}));

it('should reject if uuid is not a valid uuid', testEntities(async (service) => {
// Use testEntities here vs. testDataset to prepopulate with 2 entities
it('should reject if uuid is not a valid uuid', testDataset(async (service) => {
const asAlice = await service.login('alice');

await asAlice.post('/v1/projects/1/datasets/people/entities')
Expand All @@ -1146,6 +1145,36 @@ describe('Entities API', () => {
.expect(400);
}));

it('should reject if label is blank', testEntities(async (service) => {
const asAlice = await service.login('alice');

await asAlice.post('/v1/projects/1/datasets/people/entities')
.send({
uuid: '12345678-1234-4123-8234-123456789abc',
label: '',
data: {
first_name: 'Johnny',
age: '22'
}
})
.expect(400);
}));


it('should reject if label is not provided', testEntities(async (service) => {
const asAlice = await service.login('alice');

await asAlice.post('/v1/projects/1/datasets/people/entities')
.send({
uuid: '12345678-1234-4123-8234-123456789abc',
data: {
first_name: 'Johnny',
age: '22'
}
})
.expect(400);
}));

it('should reject if uuid is not unique', testEntities(async (service) => {
// Use testEntities here vs. testDataset to prepopulate with 2 entities
const asAlice = await service.login('alice');
Expand Down Expand Up @@ -1856,6 +1885,52 @@ describe('Entities API', () => {

});

describe('create new entities from submissions', () => {
// More success and error cases in test/integration/worker/entity.js
it('should create entity', testEntityUpdates(async (service, container) => {
const asAlice = await service.login('alice');

await asAlice.post('/v1/projects/1/forms/simpleEntity/submissions')
.send(testData.instances.simpleEntity.three)
.set('Content-Type', 'application/xml')
.expect(200);

await exhaust(container);

await asAlice.get('/v1/projects/1/datasets/people/entities/12345678-1234-4123-8234-123456789bbb')
.expect(200)
.then(({ body: person }) => {
person.currentVersion.label.should.equal('John (40)');
person.currentVersion.data.should.eql({ age: '40', first_name: 'John' });
person.currentVersion.version.should.equal(1);
});
}));

it('should not create entity if the label is missing in the submission', testEntityUpdates(async (service, container) => {
const asAlice = await service.login('alice');

await asAlice.post('/v1/projects/1/forms/simpleEntity/submissions')
.send(testData.instances.simpleEntity.three
.replace('<entities:label>John (40)</entities:label>', ''))
.set('Content-Type', 'application/xml')
.expect(200);

await exhaust(container);

await asAlice.get('/v1/projects/1/datasets/people/entities/12345678-1234-4123-8234-123456789bbb')
.expect(404);

await asAlice.get('/v1/projects/1/forms/simpleEntity/submissions/three/audits')
.expect(200)
.then(({ body: logs }) => {
logs[0].should.be.an.Audit();
logs[0].action.should.be.eql('entity.error');
logs[0].details.problem.problemCode.should.equal(400.2);
logs[0].details.errorMessage.should.equal('Required parameter label missing.');
});
}));
});

describe('entity updates from submissions', () => {
it('should process multiple updates in a row', testEntityUpdates(async (service, container) => {
const asAlice = await service.login('alice');
Expand Down Expand Up @@ -2002,8 +2077,8 @@ describe('Entities API', () => {
});
}));

describe('not updating because of errors', () => {
// more checks of erros are found in worker/entity tests
describe('update error cases', () => {
// more checks of errors are found in worker/entity tests
it('should log an error and not update if baseVersion is missing', testEntityUpdates(async (service, container) => {
const asAlice = await service.login('alice');

Expand Down Expand Up @@ -2053,6 +2128,32 @@ describe('Entities API', () => {
logs[0].details.errorMessage.should.equal('Base version (2) does not exist for entity UUID (12345678-1234-4123-8234-123456789abc) in dataset (people).');
});
}));

it('should log an error and if baseVersion is not an integer', testEntityUpdates(async (service, container) => {
const asAlice = await service.login('alice');

await asAlice.post('/v1/projects/1/forms/updateEntity/submissions')
.send(testData.instances.updateEntity.one
.replace('baseVersion="1"', 'baseVersion="not_an_integer"'))
.expect(200);

await exhaust(container);

await asAlice.get('/v1/projects/1/datasets/people/entities/12345678-1234-4123-8234-123456789abc')
.expect(200)
.then(({ body: person }) => {
person.currentVersion.version.should.equal(1);
});

await asAlice.get('/v1/projects/1/forms/updateEntity/submissions/one/audits')
.expect(200)
.then(({ body: logs }) => {
logs[0].should.be.an.Audit();
logs[0].action.should.be.eql('entity.error');
logs[0].details.problem.problemCode.should.equal(400.11);
logs[0].details.errorMessage.should.equal('Invalid input data type: expected (baseVersion) to be (integer)');
});
}));
});
});
});
85 changes: 53 additions & 32 deletions test/unit/data/entity.js
Original file line number Diff line number Diff line change
Expand Up @@ -333,34 +333,27 @@ describe('extracting and validating entities', () => {
});
});

it('should allow label to be missing (will be validated elsewhere in create case)', () => {
it('should reject if label is missing AND in create case (no existingEntity)', () => {
const body = {
uuid: '12345678-1234-4123-8234-123456789abc',
data: { age: '88' }
};
const propertyNames = ['age'];
const entity = extractEntity(body, propertyNames);
should(entity).eql({
system: {
uuid: '12345678-1234-4123-8234-123456789abc'
},
data: { age: '88' }
assert.throws(() => { extractEntity(body, propertyNames); }, (err) => {
err.problemCode.should.equal(400.2);
err.message.should.equal('Required parameter label missing.');
return true;
});
});

it('should reject if required part of the request is missing or not a string', () => {
it('should reject if required part of the request is null or not a string in create', () => {
// These are JSON entity validation errors so they use a newer 400 bad request problem
const requests = [
[
{ uuid: '12345678-1234-4123-8234-123456789abc', label: 1234, data: { first_name: 'Alice' } },
400.11,
'Invalid input data type: expected (label) to be (string)'
],
[
{ uuid: '12345678-1234-4123-8234-123456789abc' },
400.28,
'The entity is invalid. No entity data or label provided.'
],
[
{ uuid: '12345678-1234-4123-8234-123456789abc', label: 'Label', data: { first_name: 'Alice', age: 99 } },
400.11,
Expand Down Expand Up @@ -412,6 +405,28 @@ describe('extracting and validating entities', () => {
});
});

it('should allow updating properties not included in earlier version of entity', () => {
const existingEntity = {
system: {
uuid: '12345678-1234-4123-8234-123456789abc',
label: 'Label',
},
data: { first_name: 'Alice' }
};
const newData = {
data: { age: '99' }
};
const propertyNames = ['age', 'first_name'];
const entity = extractEntity(newData, propertyNames, existingEntity);
should(entity).eql({
system: {
label: 'Label',
uuid: '12345678-1234-4123-8234-123456789abc'
},
data: { age: '99', first_name: 'Alice' }
});
});

it('should allow only label to be updated without changing data', () => {
const existingEntity = {
system: {
Expand All @@ -434,29 +449,39 @@ describe('extracting and validating entities', () => {
});
});

it('should allow updating properties not included in earlier version of entity', () => {
const existingEntity = {
system: {
uuid: '12345678-1234-4123-8234-123456789abc',
label: 'Label',
},
data: { first_name: 'Alice' }
};
const newData = {
data: { age: '99' }
it('should allow label to be missing and use label of existing entity', () => {
const existingEntity = { system: { uuid: '12345678-1234-4123-8234-123456789abc', label: 'previous_label' }, data: {} };
const body = {
uuid: '12345678-1234-4123-8234-123456789abc',
data: { age: '88' }
};
const propertyNames = ['age', 'first_name'];
const entity = extractEntity(newData, propertyNames, existingEntity);
const propertyNames = ['age'];
const entity = extractEntity(body, propertyNames, existingEntity);
should(entity).eql({
system: {
label: 'Label',
label: 'previous_label',
uuid: '12345678-1234-4123-8234-123456789abc'
},
data: { age: '99', first_name: 'Alice' }
data: { age: '88' }
});
});

it('should reject if blank label provided in update', () => {
const existingEntity = { system: { uuid: '12345678-1234-4123-8234-123456789abc', label: 'previous_label' }, data: {} };
const body = {
uuid: '12345678-1234-4123-8234-123456789abc',
label: '',
data: { age: '88' }
};
const propertyNames = ['age'];
assert.throws(() => { extractEntity(body, propertyNames, existingEntity); }, (err) => {
err.problemCode.should.equal(400.8);
err.message.should.match('Unexpected label value (empty string); Label cannot be blank.');
return true;
});
});

it('should reject if required part of the request is missing or not a string', () => {
it('should reject if required part of the request is missing or not a string in update', () => {
const requests = [
[
{},
Expand All @@ -466,10 +491,6 @@ describe('extracting and validating entities', () => {
{ label: null },
400.28, 'The entity is invalid. No entity data or label provided.'
],
[
{ label: '' },
400.8, 'Unexpected label value (empty string); Label cannot be blank.'
],
[
{ data: { first_name: 'Alice', age: 99 } },
400.11, 'Invalid input data type: expected (age) to be (string)'
Expand Down

0 comments on commit 0dcb9c2

Please sign in to comment.