test/unit/services.flow.key-value.v3.js
import test from 'ava';
import nock from 'nock';
import {
client,
flowService,
Flow,
FlowKeyValue,
FlowDataGroup,
User,
} from '../../src';
test.before('start server', () => {
client.apiBaseUrl = 'https://somesite.Clinical6.com';
});
test.after('server shut down', () => {});
test.beforeEach((t) => {
// client.cache = 'never';
client.authToken = 'valid_token';
nock(client.apiBaseUrl).delete(/\/v3\/data_collection\/flow_process_values\/(\d*)$/).reply(200, { status: 'ok' });
// nock(client.apiBaseUrl).get(`/v3/data_collection/flow_process_values`).reply(200, { data: [] });
nock(client.apiBaseUrl).get(`/v3/data_collection/flow_process_values/14`).reply(200, {
data: {
id: 'dummy_476_published_14',
type: 'data_collection__flow_process_values',
attributes: {
22: 5,
23: 0
},
relationships: {
flow_process: {
data: {
id: '63',
type: 'data_collection__flow_processes'
}
},
captured_value_group: {
data: {
id: '14',
type: 'data_collection__captured_value_groups'
}
},
owner: {
data: {
id: '74',
type: 'mobile_users'
}
}
}
},
included: [
{
id: '63',
type: 'data_collection__flow_processes',
attributes: {
name: 'nostrum',
permanent_link: 'dummy_476_published',
consent_credentials: null,
created_at: '2018-01-24T18:55:35Z',
updated_at: '2018-01-24T18:55:35Z',
owner_type: 'MobileUser',
published_at: '2018-01-24T18:55:35Z',
conditional_paths: null
},
relationships: {
linked_steps: {
data: [
{
id: '18',
type: 'data_collection__linked_steps'
},
{
id: '19',
type: 'data_collection__linked_steps'
},
{
id: '20',
type: 'data_collection__linked_steps'
},
{
id: '21',
type: 'data_collection__linked_steps'
},
{
id: '22',
type: 'data_collection__linked_steps'
},
{
id: '23',
type: 'data_collection__linked_steps'
}
]
},
published: {
data: null
},
draft: {
data: {
id: '62',
type: 'data_collection__flow_processes'
}
},
initial_step: {
data: {
id: '18',
type: 'data_collection__linked_steps'
}
}
}
},
{
id: '14',
type: 'data_collection__captured_value_groups',
attributes: {
submitted_at: '2018-01-24T18:55:35Z',
created_at: '2018-01-24T18:55:35Z',
updated_at: '2018-01-24T18:55:36Z',
owner_type: 'MobileUser',
final_submission: false
},
relationships: {
owner: {
data: {
id: '74',
type: 'mobile_users'
}
},
creator: {
data: null
},
flow_process: {
data: {
id: '63',
type: 'data_collection__flow_processes'
}
},
captured_values: {
data: [
{
id: '6',
type: 'data_collection__captured_values'
},
{
id: '7',
type: 'data_collection__captured_values'
}
]
},
status: {
data: null
},
ediary_entry: {
data: null
}
}
},
{
id: '74',
type: 'mobile_users',
attributes: {
uuid: 'a6ff9423-c9e6-4101-bc2e-dd1fb2338007',
account_name: 'dummy_70',
email: 'user121@fake.com',
created_at: '2018-01-24T18:55:35Z',
updated_at: '2018-01-24T18:55:36Z',
verified_at: null,
invitation_sent_at: null,
invitation_accepted_at: null,
disabled: false,
disabled_at: null
},
relationships: {
devices: {
data: []
},
user_role: {
data: {
id: '81',
type: 'user_roles'
}
},
profile: {
data: {
id: '124',
type: 'profiles'
}
},
language: {
data: {
id: '1',
type: 'languages'
}
},
patient: {
data: null
}
}
}
]
});
// nock(client.apiBaseUrl).patch(`/v3/reminder/flows/*`).reply(200, { data: {} });
t.context.storage = client.storageUtility;
// t.context.flowJsonApi = {
// data: {
// id: 7,
// type: 'reminder__flows',
// attributes: {
// date: '2016-06-06T00:00:00Z'
// },
// relationships: {
// rule: {
// data: {
// type: 'reminder__rules',
// id: 19
// }
// },
// mobile_user: {
// data: {
// type: 'mobile_users',
// id: 215
// }
// }
// }
// }
// };
t.context.keyValue = new FlowKeyValue({ id: 901 });
});
// FlowService.deleteKeyValue method
/**
* @test {FlowService.deleteKeyValue}
*/
test('[unit] FlowService.deleteKeyValue should throw errors for invalid parameters', async (t) => {
const err = `FlowService.deleteKeyValue error`;
await t.throwsAsync(flowService.deleteKeyValue(), `${err}: keyValue is not defined`);
await t.throwsAsync(flowService.deleteKeyValue({}), `${err}: keyValue does not have id`);
});
/**
* @test {FlowService.deleteKeyValue}
*/
test('[unit] FlowService.deleteKeyValue should make a properly formatted delete request and a valid response', async (t) => {
const { keyValue } = t.context;
const response = await flowService.deleteKeyValue(keyValue);
// const request = t.context.server.requests[0];
// t.is(request.method, 'DELETE');
// t.is(request.url, `${client.apiBaseUrl}/v3/data_collection/flow_process_values/${keyValue.id}`);
// t.is(request.requestHeaders.Accept, 'application/json');
// t.is(request.requestHeaders['Content-Type'], 'application/json;charset=utf-8');
// t.is(request.requestHeaders.Authorization, 'Token token=valid_token');
t.truthy(response);
});
/**
* @test {FlowService.deleteKeyValue}
*/
test.serial('[unit] FlowService.deleteKeyValue should remove the element from local storage', async (t) => {
const { keyValue, storage } = t.context;
await keyValue.store();
t.is(storage.has(keyValue.type, keyValue.id), true, 'Storage should have data with id');
await flowService.deleteKeyValue(keyValue, 'networkFirst');
t.is(storage.has(keyValue.type, keyValue.id), false, 'Storage should not have data with id');
});
// FlowService.getKeyValue method
/**
* @test {FlowService.getKeyValue}
*/
test.serial('[unit] FlowService.getKeyValue should throw an error when there is no authToken', (t) => {
client.authToken = undefined;
const expectedError = 'FlowService.getKeyValue error: requires authToken';
t.throws(() => flowService.getKeyValue(), expectedError);
});
// /**
// * @test {FlowService.getKeyValue}
// */
// test('[unit] FlowService.getKeyValue should make a properly formatted get request', async (t) => {
// await flowService.getKeyValue();
// const request = t.context.server.requests[0];
// t.is(request.method, 'GET');
// t.is(request.url, `${client.apiBaseUrl}/v3/data_collection/captured_value_groups`);
// t.is(request.requestHeaders.Accept, 'application/json');
// t.is(request.requestHeaders['Content-Type'], 'application/json;charset=utf-8');
// t.is(request.requestHeaders.Authorization, 'Token token=valid_token');
// });
// /**
// * @test {FlowService.getKeyValue}
// */
// test('[unit] FlowService.getKeyValue should receive a valid response for a get request without an id', async (t) => {
// const response = await flowService.getKeyValue();
// t.truthy(response);
// t.is(Object.keys(response).length, 3);
// });
/**
* @test {FlowService.getKeyValue}
*/
test('[unit] FlowService.getKeyValue should receive a valid response for a get request with an id', async (t) => {
const response = await flowService.getKeyValue({ id: 14 });
// const request = t.context.server.requests[0];
// t.is(request.method, 'GET');
// t.is(request.url, `${client.apiBaseUrl}/v3/data_collection/flow_process_values/14`);
// t.is(request.requestHeaders.Accept, 'application/json');
// t.is(request.requestHeaders['Content-Type'], 'application/json;charset=utf-8');
// t.is(request.requestHeaders.Authorization, 'Token token=valid_token');
t.truthy(response);
// console.log(response);
t.is(response.id, 'dummy_476_published_14');
t.is(response.type, 'data_collection__flow_process_values');
t.is(response['22'], 5);
t.is(response['23'], 0);
t.true(response.flow instanceof Flow);
t.is(response.flow.type, 'data_collection__flow_processes');
t.is(response.flow.id, 63);
t.is(response.flow.permanentLink, 'dummy_476_published');
t.is(response.flow.name, 'nostrum');
t.is(response.flow.total, 6);
t.is(response.flow.steps.length, 6);
t.true(response.owner instanceof User);
t.is(response.owner.type, 'mobile_users');
t.is(response.owner.id, 74);
t.true(response.flowDataGroup instanceof FlowDataGroup);
t.is(response.flowDataGroup.type, 'data_collection__captured_value_groups');
t.is(response.flowDataGroup.id, 14);
t.is(response.flowDataGroup.ownerType, 'MobileUser');
t.is(response.flowDataGroup.createdAt, '2018-01-24T18:55:35Z');
t.is(response.flowDataGroup.updatedAt, '2018-01-24T18:55:36Z');
});
// FlowService.insertKeyValue method
/**
* @test {FlowService.insertKeyValue}
*/
test.serial('[unit] FlowService.insertKeyValue should throw an error when there is no authToken', (t) => {
const title = `FlowService.insertKeyValue error`;
client.authToken = undefined;
const v = new FlowKeyValue();
v.flow = new Flow({ id: 5 });
v.owner = { id: 5, type: 'mobile_users' };
t.throws(() => flowService.insertKeyValue(v), `${title}: requires authToken`);
});
/**
* @test {FlowService.insertKeyValue}
*/
test('[unit] FlowService.insertKeyValue should throw an error when parameters are invalid', (t) => {
const title = `FlowService.insertKeyValue error`;
const v = new FlowKeyValue();
t.throws(() => flowService.insertKeyValue(v), `${title}: keyValue does not have flow`);
v.owner = undefined;
v.flow = new Flow();
t.throws(() => flowService.insertKeyValue(v), `${title}: flow does not have id and owner does not have id`);
v.flow.id = 5;
t.throws(() => flowService.insertKeyValue(v), `${title}: owner does not have id`);
v.owner = { id: 25 };
t.throws(() => flowService.insertKeyValue(v), `${title}: owner does not have type`);
v.owner.type = 'mobile_users';
v.flowDataGroup = new FlowDataGroup({ });
});
/**
* @test {FlowService.insertKeyValue}
*/
test('[unit] FlowService.insertKeyValue should successfully start a flow with a flow key value object', async (t) => {
nock(client.apiBaseUrl).post(`/v3/data_collection/flow_process_values`).reply(201, {
data: {
id: 'dummy_660_published_22',
type: 'data_collection__flow_process_values',
attributes: {
46: 'male',
47: 15
},
relationships: {
flow_process: {
data: {
id: '90',
type: 'data_collection__flow_processes'
}
},
captured_value_group: {
data: {
id: '22',
type: 'data_collection__captured_value_groups'
}
},
owner: {
data: {
id: '58',
type: 'mobile_users'
}
}
}
},
included: [
{
id: '90',
type: 'data_collection__flow_processes',
attributes: {
name: 'repellendus',
permanent_link: 'dummy_660_published',
consent_credentials: null,
created_at: '2018-01-11T20:52:56Z',
updated_at: '2018-01-11T20:52:57Z',
owner_type: 'MobileUser',
published_at: '2018-01-11T20:52:57Z',
conditional_paths: null
},
relationships: {
linked_steps: {
data: [
{
id: '43',
type: 'data_collection__linked_steps'
},
{
id: '44',
type: 'data_collection__linked_steps'
},
{
id: '45',
type: 'data_collection__linked_steps'
},
{
id: '46',
type: 'data_collection__linked_steps'
},
{
id: '47',
type: 'data_collection__linked_steps'
},
{
id: '48',
type: 'data_collection__linked_steps'
}
]
},
published: {
data: null
},
draft: {
data: {
id: '89',
type: 'data_collection__flow_processes'
}
},
initial_step: {
data: {
id: '43',
type: 'data_collection__linked_steps'
}
}
}
},
{
id: '22',
type: 'data_collection__captured_value_groups',
attributes: {
submitted_at: '2018-01-11T20:52:58Z',
created_at: '2018-01-11T20:52:58Z',
updated_at: '2018-01-11T20:52:58Z',
owner_type: 'MobileUser',
final_submission: false
},
relationships: {
owner: {
data: {
id: '58',
type: 'mobile_users'
}
},
creator: {
data: {
id: '58',
type: 'mobile_users'
}
},
flow_process: {
data: {
id: '90',
type: 'data_collection__flow_processes'
}
},
captured_values: {
data: [
{
id: '5',
type: 'data_collection__captured_values'
},
{
id: '6',
type: 'data_collection__captured_values'
}
]
},
status: {
data: {
id: '34',
type: 'statuses'
}
},
ediary_entry: {
data: null
}
}
},
{
id: '58',
type: 'mobile_users',
attributes: {
uuid: 'ba6f338e-10c5-4da4-a85a-623544ca170f',
account_name: 'dummy_51',
email: 'user116@fake.com',
created_at: '2018-01-11T20:52:57Z',
updated_at: '2018-01-11T20:52:57Z',
verified_at: null,
invitation_sent_at: null,
invitation_accepted_at: null,
disabled: false,
disabled_at: null
},
relationships: {
devices: {
data: []
},
user_role: {
data: null
},
profile: {
data: {
id: '125',
type: 'profiles'
}
},
language: {
data: {
id: '1',
type: 'languages'
}
},
patient: {
data: null
}
}
}
]
});
const requestJsonApi = {
data: {
type: 'data_collection__flow_process_values',
attributes: {
46: 'male',
47: 15
},
relationships: {
flow_process: {
data: {
type: 'data_collection__flow_processes',
id: 90
}
},
owner: {
data: {
type: 'mobile_users',
id: 58
}
}
}
}
};
const v = new FlowKeyValue(requestJsonApi);
v.flow = new Flow({ id: 90 });
v.flow.store();
v.owner = new User({ id: 58 });
v.owner.store();
v['46'] = 'male';
v['47'] = 15;
const response = await flowService.insertKeyValue(v);
// const request = t.context.server.requests[0];
// t.is(request.method, 'POST');
// t.is(request.url, `${client.apiBaseUrl}/v3/data_collection/flow_process_values`);
// t.is(request.requestHeaders.Accept, 'application/json');
// t.deepEqual(JSON.parse(request.requestBody), requestJsonApi);
// t.is(request.requestHeaders['Content-Type'], 'application/json;charset=utf-8');
// t.is(request.requestHeaders.Authorization, 'Token token=valid_token');
t.is(response.id, 'dummy_660_published_22');
t.is(response.type, 'data_collection__flow_process_values');
t.is(response['46'], 'male');
t.is(response['47'], 15);
t.true(response.flow instanceof Flow);
t.is(response.flow.type, 'data_collection__flow_processes');
t.is(response.flow.id, 90);
t.is(response.flow.permanentLink, 'dummy_660_published');
t.is(response.flow.name, 'repellendus');
t.is(response.flow.total, 6);
t.is(response.flow.steps.length, 6);
t.true(response.owner instanceof User);
t.is(response.owner.type, 'mobile_users');
t.is(response.owner.id, 58);
t.true(response.flowDataGroup instanceof FlowDataGroup);
t.is(response.flowDataGroup.type, 'data_collection__captured_value_groups');
t.is(response.flowDataGroup.id, 22);
t.is(response.flowDataGroup.ownerType, 'MobileUser');
t.is(response.flowDataGroup.createdAt, '2018-01-11T20:52:58Z');
t.is(response.flowDataGroup.updatedAt, '2018-01-11T20:52:58Z');
});
/**
* @test {FlowService.insertKeyValue}
*/
test('[unit] FlowService.insertKeyValue should successfully start a flow with an existing capture value group', async (t) => {
nock(client.apiBaseUrl).post(`/v3/data_collection/flow_process_values`).reply(201, {
data: {
id: 'dummy_725_published_23',
type: 'data_collection__flow_process_values',
attributes: {
56: 'male',
57: 15
},
relationships: {
flow_process: {
data: {
id: '94',
type: 'data_collection__flow_processes'
}
},
captured_value_group: {
data: {
id: '23',
type: 'data_collection__captured_value_groups'
}
},
owner: {
data: {
id: '59',
type: 'mobile_users'
}
}
}
},
included: [
{
id: '94',
type: 'data_collection__flow_processes',
attributes: {
name: 'repellendus',
permanent_link: 'dummy_725_published',
consent_credentials: null,
created_at: '2018-01-11T20:52:58Z',
updated_at: '2018-01-11T20:52:59Z',
owner_type: 'MobileUser',
published_at: '2018-01-11T20:52:59Z',
conditional_paths: null
},
relationships: {
linked_steps: {
data: [
{
id: '53',
type: 'data_collection__linked_steps'
},
{
id: '54',
type: 'data_collection__linked_steps'
},
{
id: '55',
type: 'data_collection__linked_steps'
},
{
id: '56',
type: 'data_collection__linked_steps'
},
{
id: '57',
type: 'data_collection__linked_steps'
},
{
id: '58',
type: 'data_collection__linked_steps'
}
]
},
published: {
data: null
},
draft: {
data: {
id: '93',
type: 'data_collection__flow_processes'
}
},
initial_step: {
data: {
id: '53',
type: 'data_collection__linked_steps'
}
}
}
},
{
id: '23',
type: 'data_collection__captured_value_groups',
attributes: {
submitted_at: '2018-01-11T20:52:59Z',
created_at: '2018-01-11T20:52:59Z',
updated_at: '2018-01-11T20:52:59Z',
owner_type: 'MobileUser',
final_submission: false
},
relationships: {
owner: {
data: {
id: '60',
type: 'mobile_users'
}
},
creator: {
data: null
},
flow_process: {
data: {
id: '94',
type: 'data_collection__flow_processes'
}
},
captured_values: {
data: [
{
id: '7',
type: 'data_collection__captured_values'
},
{
id: '8',
type: 'data_collection__captured_values'
}
]
},
status: {
data: {
id: '41',
type: 'statuses'
}
},
ediary_entry: {
data: null
}
}
},
{
id: '59',
type: 'mobile_users',
attributes: {
uuid: '7954798b-95e9-4ad4-be57-7e72637dcbae',
account_name: 'dummy_52',
email: 'user117@fake.com',
created_at: '2018-01-11T20:52:59Z',
updated_at: '2018-01-11T20:52:59Z',
verified_at: null,
invitation_sent_at: null,
invitation_accepted_at: null,
disabled: false,
disabled_at: null
},
relationships: {
devices: {
data: []
},
user_role: {
data: null
},
profile: {
data: {
id: '126',
type: 'profiles'
}
},
language: {
data: {
id: '1',
type: 'languages'
}
},
patient: {
data: null
}
}
}
]
});
const requestJsonApi = {
data: {
type: 'data_collection__flow_process_values',
attributes: {
56: 'male',
57: 15
},
relationships: {
flow_process: {
data: {
type: 'data_collection__flow_processes',
id: 94
}
},
owner: {
data: {
type: 'mobile_users',
id: 59
}
},
captured_value_group: {
data: {
type: 'data_collection__captured_value_groups',
id: 23
}
}
}
}
};
const v = new FlowKeyValue(requestJsonApi);
v.flow = new Flow({ id: 94 });
v.flow.store();
v.owner = new User({ id: 59 });
v.owner.store();
v.flowDataGroup = new FlowDataGroup({ id: 23 });
v.flowDataGroup.store();
v['56'] = 'male';
v['57'] = 15;
const response = await flowService.insertKeyValue(v);
// const request = t.context.server.requests[0];
// t.is(request.method, 'POST');
// t.is(request.url, `${client.apiBaseUrl}/v3/data_collection/flow_process_values`);
// t.is(request.requestHeaders.Accept, 'application/json');
// t.deepEqual(JSON.parse(request.requestBody), requestJsonApi);
// t.is(request.requestHeaders['Content-Type'], 'application/json;charset=utf-8');
// t.is(request.requestHeaders.Authorization, 'Token token=valid_token');
t.is(response.id, 'dummy_725_published_23');
t.is(response.type, 'data_collection__flow_process_values');
t.is(response['56'], 'male');
t.is(response['57'], 15);
t.true(response.flow instanceof Flow);
t.is(response.flow.type, 'data_collection__flow_processes');
t.is(response.flow.id, 94);
t.is(response.flow.permanentLink, 'dummy_725_published');
t.is(response.flow.name, 'repellendus');
t.is(response.flow.total, 6);
t.is(response.flow.steps.length, 6);
t.true(response.owner instanceof User);
t.is(response.owner.type, 'mobile_users');
t.is(response.owner.id, 59);
t.true(response.flowDataGroup instanceof FlowDataGroup);
t.is(response.flowDataGroup.type, 'data_collection__captured_value_groups');
t.is(response.flowDataGroup.id, 23);
t.is(response.flowDataGroup.ownerType, 'MobileUser');
t.is(response.flowDataGroup.createdAt, '2018-01-11T20:52:59Z');
t.is(response.flowDataGroup.updatedAt, '2018-01-11T20:52:59Z');
});
// FlowService.insert method
/**
* @test {FlowService.insert}
*/
// test('[unit] FlowService.insert should throw an error with an invalid token', async (t) => {
// flowService.cacheMode = 'networkOnly';
// nock(client.apiBaseUrl).post(`/v3/reminder/flows`).reply()
// [422, { 'Content-Type': 'application/json' }, JSON.stringify({
// errors: [
// {
// source: {
// pointer: '/data/attributes/mobile_application_key'
// },
// detail: 'can\'t be blank'
// }
// ]
// })]
// );
// const requestJsonApi = {
// data: {
// type: 'flows',
// attributes: {
// push_id: 'FAKE_ID',
// mobile_application_key: 'invalid'
// }
// }
// };
// client.mobileApplicationKey = 'invalid';
// let response;
// await flowService.insert().catch(res => (response = res));
// const request = t.context.server.requests[0];
// t.is(request.method, 'POST');
// t.is(request.url, `${client.apiBaseUrl}/v3/reminder/flows`);
// t.is(request.requestHeaders.Accept, 'application/json');
// t.is(request.requestBody, JSON.stringify(requestJsonApi));
// t.is(request.requestHeaders['Content-Type'], 'application/json;charset=utf-8');
// t.is(request.requestHeaders.Authorization, 'Token token=valid_token');
// t.truthy(response);
// });
// // FlowService.update method
// /**
// * @test {FlowService.update}
// */
// test('[unit] FlowService.update should throw errors for invalid parameters', (t) => {
// const undefinedError = 'FlowService.update error: flow is not defined';
// t.throws(() => flowService.update(), undefinedError);
// });
// /**
// * @test {FlowService.update}
// */
// test('[unit] FlowService.update should successfully update a flow with a flow object', async (t) => {
// const { flow, flowJsonApi } = t.context;
// const response = await flowService.update(flow);
// const request = t.context.server.requests[0];
// t.is(request.method, 'PATCH');
// t.is(request.url, `${client.apiBaseUrl}/v3/reminder/flows/${flow.id}`);
// t.is(request.requestHeaders.Accept, 'application/json');
// t.deepEqual(JSON.parse(request.requestBody), flowJsonApi);
// t.is(request.requestHeaders['Content-Type'], 'application/json;charset=utf-8');
// t.is(request.requestHeaders.Authorization, 'Token token=valid_token');
// t.is(response.id, 7);
// t.is(response.type, 'reminder__flows');
// t.is(response.createdAt, '2017-09-12T05:36:52Z');
// t.is(response.updatedAt, '2017-09-12T05:36:52Z');
// t.is(response.date, '2016-06-06T00:00:00Z');
// t.is(response.status, 5);
// t.is(response.rule.id, 19);
// t.is(response.rule.type, 'reminder__rules');
// t.is(response.mobileUser.id, 215);
// t.is(response.mobileUser.type, 'mobile_users');
// });