test/unit/services.cohort.js
import test from 'ava';
import nock from 'nock';
import {
client,
clinical6,
Cohort,
CohortAssignment,
} from '../../src';
test.before('start server', (t) => {
t.context.storage = client.storageUtility;
client.apiBaseUrl = 'https://somesite.Clinical6.com';
t.context.getResponseAll = {
data: [
{
id: '17',
type: 'cohorts',
attributes: {
name: 'name-17',
cohort_type: 'static',
created_at: '2018-04-17T16:14:07Z',
updated_at: '2018-04-17T16:14:07Z'
}
},
{
id: '18',
type: 'cohorts',
attributes: {
name: 'name-18',
cohort_type: 'static',
created_at: '2018-04-17T16:14:07Z',
updated_at: '2018-04-17T16:14:07Z'
}
},
{
id: '19',
type: 'cohorts',
attributes: {
name: 'name-19',
cohort_type: 'static',
created_at: '2018-04-17T16:14:07Z',
updated_at: '2018-04-17T16:14:07Z'
}
},
{
id: '20',
type: 'cohorts',
attributes: {
name: 'name-20',
cohort_type: 'dynamic',
created_at: '2018-04-17T16:14:07Z',
updated_at: '2018-04-17T16:14:07Z'
},
relationships: {
filter_group: {
data: {
id: '3',
type: 'filter_groups'
}
}
}
},
{
id: '21',
type: 'cohorts',
attributes: {
name: 'name-21',
cohort_type: 'dynamic',
created_at: '2018-04-17T16:14:07Z',
updated_at: '2018-04-17T16:14:07Z'
},
relationships: {
filter_group: {
data: {
id: '4',
type: 'filter_groups'
}
}
}
}
],
included: [
{
id: '3',
type: 'filter_groups',
attributes: {
operator: 'and',
created_at: '2018-04-17T16:14:07Z',
updated_at: '2018-04-17T16:14:07Z'
},
relationships: {
cohort: {
data: {
id: '20',
type: 'cohorts'
}
}
}
},
{
id: '4',
type: 'filter_groups',
attributes: {
operator: 'and',
created_at: '2018-04-17T16:14:07Z',
updated_at: '2018-04-17T16:14:07Z'
},
relationships: {
cohort: {
data: {
id: '21',
type: 'cohorts'
}
}
}
}
]
};
t.context.getResponseId = {
data: {
id: '23',
type: 'cohorts',
attributes: {
name: 'name-25',
cohort_type: 'dynamic',
created_at: '2018-04-17T16:14:08Z',
updated_at: '2018-04-17T16:14:08Z'
},
relationships: {
filter_group: {
data: {
id: '5',
type: 'filter_groups'
}
}
}
},
included: [
{
id: '5',
type: 'filter_groups',
attributes: {
operator: 'and',
created_at: '2018-04-17T16:14:08Z',
updated_at: '2018-04-17T16:14:08Z'
},
relationships: {
cohort: {
data: {
id: '23',
type: 'cohorts'
}
}
}
}
]
};
t.context.getResponseAssignments = {
data: [
{
id: '4',
type: 'cohort_assignments',
attributes: {
created_at: '2018-04-17T19:59:54Z',
updated_at: '2018-04-17T19:59:54Z'
},
relationships: {
user: {
data: {
id: '152',
type: 'users'
}
},
cohort: {
data: {
id: '9',
type: 'cohorts'
}
}
}
},
{
id: '5',
type: 'cohort_assignments',
attributes: {
created_at: '2018-04-17T19:59:54Z',
updated_at: '2018-04-17T19:59:54Z'
},
relationships: {
user: {
data: {
id: '153',
type: 'users'
}
},
cohort: {
data: {
id: '9',
type: 'cohorts'
}
}
}
},
{
id: '6',
type: 'cohort_assignments',
attributes: {
created_at: '2018-04-17T19:59:54Z',
updated_at: '2018-04-17T19:59:54Z'
},
relationships: {
user: {
data: {
id: '154',
type: 'users'
}
},
cohort: {
data: {
id: '9',
type: 'cohorts'
}
}
}
}
],
included: [
{
id: '152',
type: 'users',
attributes: {
uuid: '7731e5db-3c94-4596-8a52-cb753b9d23bd',
email: 'user418@fake.com',
created_at: '2018-04-17T19:59:54Z',
updated_at: '2018-04-17T19:59:54Z',
invitation_sent_at: null,
invitation_accepted_at: null,
disabled_at: null
},
relationships: {
user_role: {
data: {
id: '192',
type: 'user_roles'
}
},
devices: {
data: []
},
profile: {
data: {
id: '431',
type: 'profiles'
}
}
}
},
{
id: '153',
type: 'users',
attributes: {
uuid: '6d97ee61-543f-4778-adea-c2a3537d4532',
email: 'user419@fake.com',
created_at: '2018-04-17T19:59:54Z',
updated_at: '2018-04-17T19:59:54Z',
invitation_sent_at: null,
invitation_accepted_at: null,
disabled_at: null
},
relationships: {
user_role: {
data: {
id: '192',
type: 'user_roles'
}
},
devices: {
data: []
},
profile: {
data: {
id: '432',
type: 'profiles'
}
}
}
},
{
id: '154',
type: 'users',
attributes: {
uuid: '3536a5bb-0404-4202-a15e-e13b0d705c36',
email: 'user420@fake.com',
created_at: '2018-04-17T19:59:54Z',
updated_at: '2018-04-17T19:59:54Z',
invitation_sent_at: null,
invitation_accepted_at: null,
disabled_at: null
},
relationships: {
user_role: {
data: {
id: '192',
type: 'user_roles'
}
},
devices: {
data: []
},
profile: {
data: {
id: '433',
type: 'profiles'
}
}
}
}
]
};
t.context.getResponseAssignment20 = {
data: {
id: '20',
type: 'cohort_assignments',
attributes: {
created_at: '2018-04-17T19:59:53Z',
updated_at: '2018-04-17T19:59:53Z'
},
relationships: {
user: {
data: {
id: '278',
type: 'mobile_users'
}
},
cohort: {
data: {
id: '2',
type: 'cohorts'
}
}
}
},
included: [
{
id: '278',
type: 'mobile_users',
attributes: {
uuid: '7731e5db-3c94-4596-8a52-cb753b9d23bd',
email: 'user418@fake.com',
created_at: '2018-04-17T19:59:54Z',
updated_at: '2018-04-17T19:59:54Z',
invitation_sent_at: null,
invitation_accepted_at: null,
disabled_at: null
},
relationships: {
user_role: {
data: {
id: '192',
type: 'user_roles'
}
},
devices: {
data: []
},
profile: {
data: {
id: '431',
type: 'profiles'
}
}
}
}
]
};
t.context.patchResponse = {
data: {
id: '25',
type: 'cohorts',
attributes: {
name: 'new-name',
cohort_type: 'dynamic',
created_at: '2018-04-17T16:14:08Z',
updated_at: '2018-04-17T16:14:08Z'
},
relationships: {
filter_group: {
data: null
}
}
}
};
t.context.postResponse = {
data: {
id: 1,
type: 'cohorts',
attributes: {
name: 'name',
cohort_type: 'static',
created_at: '2018-04-03T14:16:25Z',
updated_at: '2018-04-03T14:16:25Z'
}
}
};
t.context.cohortJsonApi = {
data: {
id: 25,
type: 'cohorts',
attributes: {
name: 'name',
cohort_type: 'static'
}
}
};
});
test.after('server shut down', () => {});
test.beforeEach((t) => {
client.cache = 'never';
client.authToken = 'valid_token';
t.context.cohort = new Cohort(t.context.cohortJsonApi);
});
// CohortService.delete method
/**
* @test {Clinical6.delete}
*/
test('[unit] CohortService.delete should throw errors for invalid parameters', async (t) => {
const title = `CohortService.delete error`;
await t.throwsAsync(clinical6.delete(new Cohort()), `${title}: cohort does not have id`);
});
/**
* @test {Clinical6.delete}
*/
test('[unit] CohortService.delete should receive a valid response for a delete request', async (t) => {
const { cohort } = t.context;
cohort.id = 5;
let request = {};
nock(client.apiBaseUrl).delete(`/v3/cohorts/${cohort.id}`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, ''];
});
const response = await clinical6.delete(cohort);
t.is(request.path, `/v3/cohorts/${cohort.id}`);
t.is(request.headers.accept, 'application/json');
t.is(request.headers['content-type'], 'application/json');
t.is(request.headers.authorization, 'Token token=valid_token');
t.falsy(response);
});
/**
* @test {Clinical6.delete}
*/
test.serial('[unit] CohortService.delete should remove the element from local storage', async (t) => {
const { cohort, storage } = t.context;
cohort.id = 5;
nock(client.apiBaseUrl).delete(`/v3/cohorts/${cohort.id}`).reply(200, '');
await storage.set(cohort.type, cohort.toJSON(), { id: cohort.id });
await clinical6.delete(cohort);
t.is(storage.has(cohort.type, { id: cohort.id }), false);
});
// CohortService.get method
/**
* @test {Clinical6.get}
*/
test.serial('[unit] CohortService.get should throw an error when there is no authToken', async (t) => {
client.authToken = undefined;
const expectedError = 'CohortService.get error: requires authToken';
await t.throwsAsync(clinical6.get(Cohort), expectedError);
});
/**
* @test {Clinical6.get}
*/
test('[unit] CohortService.get should make a properly formatted get request and response without an id', async (t) => {
const { getResponseAll } = t.context;
let request = {};
nock(client.apiBaseUrl).get('/v3/cohorts').reply(function () {
request = this.req;
return [200, getResponseAll];
});
const response = await clinical6.get(Cohort);
t.is(request.path, `/v3/cohorts`);
t.is(request.headers.accept, 'application/json');
t.is(request.headers['content-type'], 'application/json');
t.is(request.headers.authorization, 'Token token=valid_token');
t.truthy(response);
t.is(Object.keys(response).length, 5);
});
/**
* @test {Clinical6.get}
*/
test('[unit] CohortService.get should receive a valid response for a get request with an id', async (t) => {
const { getResponseId } = t.context;
nock(client.apiBaseUrl).get('/v3/cohorts/4').reply(200, getResponseId);
const response = await clinical6.get(new Cohort({ id: 4 }));
t.truthy(response);
t.is(response.id, 23);
t.is(response.type, 'cohorts');
t.is(response.createdAt, '2018-04-17T16:14:08Z');
t.is(response.updatedAt, '2018-04-17T16:14:08Z');
t.is(response.name, 'name-25');
t.is(response.cohortType, 'dynamic');
});
// CohortService.getChildren method
/**
* @test {Clinical6.getChildren}
*/
test.serial('[unit] CohortService.getChildren should throw an error when there is no authToken or invalid params', async (t) => {
client.authToken = undefined;
const title = `CohortService.getChildren error`;
const cohort = new Cohort({ id: 22 });
await t.throwsAsync(clinical6.getChildren(cohort, CohortAssignment), `${title}: requires authToken`);
client.authToken = 'valid_authToken';
await t.throwsAsync(clinical6.getChildren(cohort), `${title}: child does not have type`);
});
/**
* @test {Clinical6.getChildren}
*/
test(`[unit] CohortService.getChildren should receive a valid request and response for a get request without an id`, async (t) => {
const { getResponseAssignments } = t.context;
const cohort = new Cohort({ id: 22 });
let request = {};
nock(client.apiBaseUrl).get(`/v3/cohorts/${cohort.id}/cohort_assignments`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, getResponseAssignments];
});
const response = await clinical6.getChildren(cohort, CohortAssignment);
t.is(request.path, `/v3/cohorts/${cohort.id}/cohort_assignments`);
t.is(request.headers.accept, 'application/json');
t.is(request.headers['content-type'], 'application/json');
t.is(request.headers.authorization, 'Token token=valid_token');
t.truthy(response);
t.is(Object.keys(response).length, 3);
t.truthy(response[0] instanceof CohortAssignment);
t.is(response[0].id, 4);
t.is(response[0].type, 'cohort_assignments');
t.is(response[0].createdAt, '2018-04-17T19:59:54Z');
t.is(response[0].updatedAt, '2018-04-17T19:59:54Z');
t.truthy(response[0].user);
t.is(response[0].user.id, 152);
t.is(response[0].user.createdAt, '2018-04-17T19:59:54Z');
t.is(response[0].user.email, 'user418@fake.com');
t.is(response[0].user.updatedAt, '2018-04-17T19:59:54Z');
t.is(response[0].user.uuid, '7731e5db-3c94-4596-8a52-cb753b9d23bd');
t.truthy(response[1] instanceof CohortAssignment);
t.is(response[1].id, 5);
t.is(response[1].type, 'cohort_assignments');
t.is(response[1].createdAt, '2018-04-17T19:59:54Z');
t.is(response[1].updatedAt, '2018-04-17T19:59:54Z');
t.truthy(response[2] instanceof CohortAssignment);
t.is(response[2].id, 6);
t.is(response[2].type, 'cohort_assignments');
t.is(response[2].createdAt, '2018-04-17T19:59:54Z');
t.is(response[2].updatedAt, '2018-04-17T19:59:54Z');
});
/**
* @test {Clinical6.getChildren}
*/
test('[unit] CohortService.getChildren should receive a valid response for a get request with an id', async (t) => {
const { getResponseAssignment20 } = t.context;
const cohort = new Cohort({ id: 22 });
const cohortAssignment = new CohortAssignment({ id: 20 });
let request = {};
nock(client.apiBaseUrl).get(`/v3/cohorts/${cohort.id}/cohort_assignments/${cohortAssignment.id}`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, getResponseAssignment20];
});
const response = await clinical6.getChildren(cohort, { id: 20, type: CohortAssignment.type });
t.is(request.path, `/v3/cohorts/${cohort.id}/cohort_assignments/${cohortAssignment.id}`);
t.is(request.headers.accept, 'application/json');
t.is(request.headers['content-type'], 'application/json');
t.is(request.headers.authorization, 'Token token=valid_token');
t.truthy(response);
t.truthy(response instanceof CohortAssignment);
t.is(response.id, 20);
t.is(response.type, 'cohort_assignments');
t.is(response.createdAt, '2018-04-17T19:59:53Z');
t.is(response.updatedAt, '2018-04-17T19:59:53Z');
t.truthy(response.user);
t.is(response.user.id, 278);
t.is(response.user.createdAt, '2018-04-17T19:59:54Z');
t.is(response.user.email, 'user418@fake.com');
t.is(response.user.updatedAt, '2018-04-17T19:59:54Z');
t.is(response.user.uuid, '7731e5db-3c94-4596-8a52-cb753b9d23bd');
t.truthy(response.cohort);
t.is(response.cohort.id, 2);
t.is(response.cohort.type, 'cohorts');
});
// CohortService.insert method
/**
* @test {Clinical6.insert}
*/
test.serial('[unit] CohortService.insert should throw an error when there is no authToken', async (t) => {
client.authToken = undefined;
const expectedError = 'CohortService.insert error: requires authToken';
await t.throwsAsync(clinical6.insert(new Cohort()), expectedError);
});
/**
* @test {Clinical6.insert}
*/
test('[unit] CohortService.insert should successfully insert a cohort with a cohort object', async (t) => {
const { postResponse } = t.context;
let request = {};
nock(client.apiBaseUrl).post(`/v3/cohorts`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, postResponse];
});
const requestJsonApi = {
data: {
type: 'cohorts',
attributes: {
name: 'name',
cohort_type: 'static'
}
}
};
const cohort = new Cohort(requestJsonApi);
const response = await clinical6.insert(cohort);
t.is(request.path, `/v3/cohorts`);
t.is(request.headers.accept, 'application/json');
t.deepEqual(request.requestBody, requestJsonApi);
t.is(request.headers['content-type'], 'application/json');
t.is(request.headers.authorization, 'Token token=valid_token');
t.is(response.id, 1);
t.is(response.type, 'cohorts');
t.is(response.name, 'name');
t.is(response.cohortType, 'static');
t.is(response.createdAt, '2018-04-03T14:16:25Z');
t.is(response.updatedAt, '2018-04-03T14:16:25Z');
});
// CohortService.update method
/**
* @test {Clinical6.update}
*/
test('[unit] CohortService.update should successfully update a cohort with a cohort object', async (t) => {
const { cohort, patchResponse, cohortJsonApi } = t.context;
let request = {};
nock(client.apiBaseUrl).patch(/\/v3\/cohorts\/([0-9]*)$/).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, patchResponse];
});
const response = await clinical6.update(cohort);
t.is(request.path, `/v3/cohorts/${cohort.id}`);
t.is(request.headers.accept, 'application/json');
t.is(request.headers['content-type'], 'application/json');
t.is(request.headers.authorization, 'Token token=valid_token');
t.deepEqual(request.requestBody, cohortJsonApi);
t.is(response.id, 25);
t.is(response.type, 'cohorts');
});