test/unit/services.consultation.js
import test from 'ava';
import nock from 'nock';
import {
client,
clinical6,
consultationService,
Consultation,
ConsultationParticipant,
} from '../../src';
test.before('start server', (t) => {
t.context.storage = client.storageUtility;
client.apiBaseUrl = 'https://somesite.Clinical6.com';
t.context.getResponseAll = {};
t.context.getResponseId = {};
t.context.patchResponse = {
data: {
id: '3',
type: 'video_consultations',
attributes: {
name: 'vc2',
start_at: '2018-07-26T02:49:20Z',
end_at: '2018-07-26T03:49:20Z',
status: 'active',
confirmed_at: null,
deleted_at: null,
created_at: '2018-07-26T02:49:20Z',
updated_at: '2018-07-26T02:49:20Z'
},
relationships: {
video_consultation_participants: {
data: []
}
}
}
};
t.context.postResponse = {
data: {
id: '4',
type: 'video_consultations',
attributes: {
name: 'Video Consultation Name',
start_at: '2018-07-26T02:49:20Z',
end_at: null,
status: null,
confirmed_at: null,
deleted_at: null,
created_at: '2018-07-26T02:49:20Z',
updated_at: '2018-07-26T02:49:20Z'
},
relationships: {
video_consultation_participants: {
data: []
}
}
}
};
t.context.joinResponse = {
data: {
id: '2',
type: 'video_consultations',
attributes: {
name: 'General Consultation',
start_at: '2018-08-09T17:59:22Z',
end_at: null,
status: null,
session_identity: '1_MX40NTYwNDkzMn5-MTUzMjM3NzM4NzEzMn5wdEM0WWx6ODZ6b3JKbWJ3aXNvNlQrbmZ-UH4',
confirmed_at: null,
deleted_at: null,
created_at: '2018-08-09T18:00:43Z',
updated_at: '2018-08-09T18:00:44Z'
},
relationships: {
video_consultation_participants: {
data: [
{
id: '1',
type: 'video_consultation_participants'
}
]
}
}
},
included: [
{
id: '1',
type: 'video_consultation_participants',
attributes: {
created_at: '2018-08-09T18:00:44Z',
updated_at: '2018-08-09T18:00:44Z'
},
relationships: {
video_consultation: {
data: {
id: '2',
type: 'video_consultations'
}
},
participant: {
data: {
id: '209',
type: 'mobile_users'
}
}
}
}
],
meta: {
join_token: 'T1==cGFydG5lcl9pZD00NTYwNDkzMiZzaWc9ZTI0MjE3NzhlYTU5MGQ4NWM1NDkwZjM1ZGE3NGE4NjZlY2NlOTliYjpyb2xlPXB1Ymxpc2hlciZzZXNzaW9uX2lkPTFfTVg0ME5UWXdORGt6TW41LU1UVXpNak0zTnpNNE56RXpNbjV3ZEVNMFdXeDZPRFo2YjNKS2JXSjNhWE52TmxRcmJtWi1VSDQmY3JlYXRlX3RpbWU9MTUzMzgzNzY0NCZub25jZT0wLjY4NjIwOTA1NTk4MTM3NzUmZXhwaXJlX3RpbWU9MTUzMzg0MTI0NCZjb25uZWN0aW9uX2RhdGE9',
api_key: '45604932'
}
};
t.context.consultationJsonApi = {
data: {
id: 3,
type: 'video_consultations',
attributes: {
name: 'Video Consultation Name',
start_at: '2018-07-26T02:49:20Z'
}
}
};
t.context.consultationParticipantJsonApi = {
id: 1,
type: 'video_consultation_participants',
attributes: {
created_at: null,
updated_at: null,
},
relationships: {
video_consultation: {
data: {
id: 1,
type: 'video_consultations'
}
}
}
};
});
test.after('server shut down', () => {});
test.beforeEach((t) => {
client.cache = 'never';
client.authToken = 'valid_token';
t.context.consultation = new Consultation(t.context.consultationJsonApi);
t.context.participant = new ConsultationParticipant(t.context.consultationParticipantJsonApi);
});
// ConsultationService.delete method
/**
* @test {Clinical6.delete}
*/
test('[unit] ConsultationService.delete should throw errors for invalid parameters', async (t) => {
const title = `ConsultationService.delete error`;
await t.throwsAsync(clinical6.delete(new Consultation()), `${title}: video_consultation does not have id`);
});
/**
* @test {Clinical6.delete}
*/
test('[unit] ConsultationService.delete should receive a valid response for a delete request', async (t) => {
const { consultation } = t.context;
consultation.id = 5;
let request = {};
nock(client.apiBaseUrl).delete(`/v3/video_consultations/${consultation.id}`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, ''];
});
const response = await clinical6.delete(consultation);
t.is(request.path, `/v3/video_consultations/${consultation.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] ConsultationService.delete should remove the element from local storage', async (t) => {
const { consultation, storage } = t.context;
consultation.id = 5;
nock(client.apiBaseUrl).delete(`/v3/video_consultations/${consultation.id}`).reply(200, '');
await storage.set(consultation.type, consultation.toJSON(), { id: consultation.id });
await clinical6.delete(consultation);
t.is(storage.has(consultation.type, { id: consultation.id }), false);
});
// ConsultationService.get method
/**
* @test {Clinical6.get}
*/
test.serial('[unit] ConsultationService.get should throw an error when there is no authToken', async (t) => {
client.authToken = undefined;
const expectedError = 'ConsultationService.get error: requires authToken';
await t.throwsAsync(clinical6.get(Consultation), expectedError);
});
// /**
// * @test {Clinical6.get}
// */
// test('[unit] ConsultationService.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/video_consultations').reply(function () {
// request = this.req;
// return [200, getResponseAll];
// });
// const response = await clinical6.get(Consultation);
// t.is(request.path, `/v3/video_consultations`);
// 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] ConsultationService.get should receive a valid response for a get request with an id', async (t) => {
// const { getResponseId } = t.context;
// nock(client.apiBaseUrl).get('/v3/video_consultations/4').reply(200, getResponseId);
// const response = await clinical6.get(new Consultation({ id: 4 }));
// t.truthy(response);
// t.is(response.id, 23);
// t.is(response.type, 'video_consultations');
// 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.consultationType, 'dynamic');
// });
// ConsultationService.insert method
/**
* @test {Clinical6.insert}
*/
test.serial('[unit] ConsultationService.insert should throw an error when there is no authToken', async (t) => {
client.authToken = undefined;
const expectedError = 'ConsultationService.insert error: requires authToken';
await t.throwsAsync(clinical6.insert(new Consultation()), expectedError);
});
/**
* @test {Clinical6.insert}
*/
test('[unit] ConsultationService.insert should successfully insert a consultation with a consultation object', async (t) => {
const { postResponse } = t.context;
let request = {};
nock(client.apiBaseUrl).post(`/v3/video_consultations`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, postResponse];
});
const requestJsonApi = {
data: {
type: 'video_consultations',
attributes: {
name: 'Video Consultation Name',
start_at: '2018-07-26T02:49:20Z'
}
}
};
const consultation = new Consultation(requestJsonApi);
const response = await clinical6.insert(consultation);
t.is(request.path, `/v3/video_consultations`);
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, 4);
t.is(response.type, 'video_consultations');
t.is(response.name, 'Video Consultation Name');
t.is(response.startAt, '2018-07-26T02:49:20Z');
t.is(response.createdAt, '2018-07-26T02:49:20Z');
t.is(response.updatedAt, '2018-07-26T02:49:20Z');
});
// ConsultationService.join method
/**
* @test {Clinical6.join}
*/
test.serial('[unit] ConsultationService.join should throw an error when there is no authToken', async (t) => {
const title = `ConsultationService.join error`;
const consultation = new Consultation();
const participant = new ConsultationParticipant();
await t.throwsAsync(consultationService.join(consultation, participant), `${title}: consultation does not have id and participant does not have id`);
consultation.id = 1;
await t.throwsAsync(consultationService.join(consultation, participant), `${title}: participant does not have id`);
participant.id = 1;
delete consultation.id;
await t.throwsAsync(consultationService.join(consultation, participant), `${title}: consultation does not have id`);
consultation.id = 1;
participant.id = 1;
await t.throwsAsync(consultationService.join(), `${title}: consultation is not defined and participant is not defined`);
await t.throwsAsync(consultationService.join(consultation), `${title}: participant is not defined`);
await t.throwsAsync(consultationService.join(undefined, participant), `${title}: consultation is not defined`);
await t.throwsAsync(consultationService.join(consultation, { id: 1 }), `${title}: participant is not a type of ConsultationParticipant`);
await t.throwsAsync(consultationService.join({ id: 1 }, participant), `${title}: consultation is not a type of Consultation`);
client.authToken = undefined;
consultation.id = 1;
participant.id = 1;
await t.throwsAsync(consultationService.join(consultation, participant), `${title}: requires authToken`);
});
/**
* @test {Clinical6.join}
*/
test('[unit] ConsultationService.join should successfully join a consultation with a consultation object', async (t) => {
const { joinResponse, consultation, participant } = t.context;
let request = {};
nock(client.apiBaseUrl).post(`/v3/video_consultation_join`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [201, joinResponse];
});
const requestJsonApi = {
data: {
type: 'video_consultation_join',
attributes: {},
relationships: {
video_consultation: {
data: {
id: 3,
type: 'video_consultations'
}
},
video_consultation_participant: {
data: {
id: 1,
type: 'video_consultation_participants'
}
}
}
}
};
const meta = {};
const response = await consultationService.join(consultation, participant, { meta });
t.is(request.path, `/v3/video_consultation_join`);
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, 2);
t.is(response.type, 'video_consultations');
t.is(response.name, 'General Consultation');
t.is(response.startAt, '2018-08-09T17:59:22Z');
t.is(meta.joinToken, `T1==cGFydG5lcl9pZD00NTYwNDkzMiZzaWc9ZTI0MjE3NzhlYTU5MGQ4NWM1NDkwZj`
+ `M1ZGE3NGE4NjZlY2NlOTliYjpyb2xlPXB1Ymxpc2hlciZzZXNzaW9uX2lkPTFfTVg0ME5UWXdORGt6TW41LU1UVXpNak`
+ `0zTnpNNE56RXpNbjV3ZEVNMFdXeDZPRFo2YjNKS2JXSjNhWE52TmxRcmJtWi1VSDQmY3JlYXRlX3RpbWU9MTUzMzgzNz`
+ `Y0NCZub25jZT0wLjY4NjIwOTA1NTk4MTM3NzUmZXhwaXJlX3RpbWU9MTUzMzg0MTI0NCZjb25uZWN0aW9uX2RhdGE9`);
});
// ConsultationService.update method
/**
* @test {Clinical6.update}
*/
test('[unit] ConsultationService.update should successfully update a consultation with a consultation object', async (t) => {
const { consultation, patchResponse, consultationJsonApi } = t.context;
let request = {};
nock(client.apiBaseUrl).patch(/\/v3\/video_consultations\/([0-9]*)$/).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, patchResponse];
});
const response = await clinical6.update(consultation);
t.is(request.path, `/v3/video_consultations/${consultation.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, consultationJsonApi);
t.is(response.id, 3);
t.is(response.type, 'video_consultations');
});