test/unit/services.flow.v3.js
import test from 'ava';
import nock from 'nock';
import { client, Flow, flowService } from '../../src';
test.before('start server', (t) => {
t.context.storage = client.storageUtility;
client.apiBaseUrl = 'https://somesite.Clinical6.com';
t.context.getResponseAll = {
data: [
{
id: 155,
type: 'data_collection__flow_processes',
attributes: {
name: 'qui',
permanent_link: 'dummy_1566',
published_at: null
}
}
]
};
t.context.patchResponse = {
data: {
id: '6',
type: 'data_collection__flow_processes',
attributes: {
name: 'Updated',
permanent_link: 'dummy_77',
consent_credentials: null,
created_at: '2018-08-19T22:03:19Z',
updated_at: '2018-08-19T22:03:20Z',
owner_type: 'MobileUser',
published_at: null,
conditional_paths: null,
description: 'Updated flow description'
},
relationships: {
linked_steps: {
data: []
},
published: {
data: null
},
draft: {
data: null
},
initial_step: {
data: null
}
}
}
};
t.context.storage = client.storageUtility;
client.flow = new Flow({});
t.context.flowJsonApi = {
data: {
type: 'data_collection/flow_processes',
attributes: {}
}
};
});
test.after('server shut down', () => {});
test.beforeEach((t) => {
client.cache = 'never';
client.authToken = 'valid_token';
t.context.flow = new Flow(t.context.flowJsonApi);
});
// FlowService.get method
/**
* @test {FlowService.get}
*/
test.serial('[unit] FlowService.get should throw an error when there is no authToken', async (t) => {
client.authToken = undefined;
const expectedError = 'FlowService.get error: requires authToken';
await t.throws(() => flowService.get(), expectedError);
});
/**
* @test {Clinical6.get}
*/
test('[unit] FlowService.get should make a properly formatted get request', async (t) => {
const { getResponseAll } = t.context;
let request = {};
nock(client.apiBaseUrl).get(`/v3/data_collection/flow_processes`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, getResponseAll];
});
await flowService.get();
t.is(request.path, `/v3/data_collection/flow_processes`);
t.is(request.headers.accept, 'application/json');
t.is(request.headers['content-type'], 'application/json');
t.is(request.headers.authorization, 'Token token=valid_token');
});
/**
* @test {FlowService.get}
*/
test('FlowService.get should receive a valid response for a get request without an id', async (t) => {
const { getResponseAll } = t.context;
nock(client.apiBaseUrl).get(`/v3/data_collection/flow_processes`).reply(200, getResponseAll);
const response = await flowService.get();
t.truthy(response);
t.is(Object.keys(response).length, 1);
t.is(response[0].id, 155);
t.is(response[0].type, 'data_collection__flow_processes');
t.is(response[0].name, 'qui');
t.is(response[0].permanentLink, 'dummy_1566');
t.is(response[0].publishedAt, null);
});
/**
* @test {FlowService.get}
*/
// test('[unit] FlowService.get should receive a valid response for a get request with an id', async (t) => {
// const response = await flowService.get({ id: 4 });
// t.truthy(response);
// t.is(response.id, 4);
// t.is(response.type, 'data_collection/flow_processes');
// t.is(response.createdAt, '2017-08-09T16:23:55Z');
// t.is(response.updatedAt, '2017-08-09T16:23:55Z');
// t.is(response.title, 'dummy_440');
// t.is(response.description, 'Demo Content info...');
// t.is(response.redemptionPoints, 250);
// t.is(response.image.url, '/uploads/test/reward/image/4/1.png');
// t.is(response.position, 4);
// t.is(response.enabled, true);
// t.is(response.featured, null);
// t.is(response.basedOn, null);
// t.is(response.threshold, null);
// t.is(response.timeUnit, null);
// t.is(response.startPoint, null);
// t.is(response.startAt, null);
// t.is(response.disabledImage.url, '/default/default.png');
// t.is(response.cacheToken, 'QBPu8whNUSE');
// });
// FlowService.delete method
/**
* @test {FlowService.delete}
*/
// test('[unit] JsonApiService.delete should throw errors for invalid parameters', async (t) => {
// const undefinedError = 'JsonApiService.delete error: obj is not defined';
// await t.throws(() => flowService.delete(), undefinedError);
// });
// /**
// * @test {FlowService.delete}
// */
// test('[unit] FlowService.delete should make a properly formatted delete request', async (t) => {
// const { flow } = t.context;
// flow.id = 5;
// await flowService.delete(flow);
// const request = t.context.server.requests[0];
// t.is(request.method, 'DELETE');
// t.is(request.url, `${client.apiBaseUrl}/v3/data_collection/flow_processes/${flow.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');
// });
/**
* @test {FlowService.delete}
*/
test('[unit] FlowService.delete should receive a valid response for a delete request', async (t) => {
const { flow } = t.context;
flow.id = 5;
let request = {};
nock(client.apiBaseUrl).delete(`/v3/data_collection/flow_processes/5`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, ''];
});
const response = await flowService.delete(flow);
t.is(request.path, `/v3/data_collection/flow_processes/5`);
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 {FlowService.delete}
*/
test('[unit] FlowService.delete should remove the element from local storage', async (t) => {
const { flow, storage } = t.context;
flow.id = 5;
nock(client.apiBaseUrl).delete(`/v3/data_collection/flow_processes/5`).reply(204, '');
await storage.set('data_collection/flow_processes', flow.toJSON(), { id: flow.id });
await flowService.delete(flow);
t.is(storage.has('data_collection/flow_processes', { id: flow.id }), false);
});
// FlowService.insert method
/**
* @test {FlowService.insert}
*/
test.serial('[unit] [unit] FlowService.insert should throw an error when there is no authToken', async (t) => {
client.authToken = undefined;
const expectedError = 'FlowService.insert error: requires authToken';
await t.throws(() => flowService.insert({}), expectedError);
});
/**
* @test {FlowService.insert}
*/
test('[unit] FlowService.insert should successfully insert a flow with a flow object', async (t) => {
let request = {};
nock(client.apiBaseUrl).post(`/v3/data_collection/flow_processes`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [201, {
data: {
id: '2',
type: 'data_collection__flow_processes',
attributes: {
name: 'Flow Name',
permanent_link: 'flow_name',
consent_credentials: null,
created_at: '2018-03-01T21:25:00Z',
updated_at: '2018-03-01T21:25:00Z',
owner_type: 'MobileUser',
published_at: null,
conditional_paths: null
},
relationships: {
linked_steps: { data: [] },
published: { data: null },
draft: { data: null },
initial_step: { data: null }
}
}
}];
});
const requestJsonApi = {
data: {
type: 'data_collection__flow_processes',
attributes: {
name: 'Flow Name',
permanent_link: 'flow_name',
steps: []
}
}
};
client.mobileApplicationKey = '0355b2fb1c8fa7210bec203abb32b916';
const flow = new Flow(requestJsonApi);
const response = await flowService.insert(flow);
t.is(request.path, `/v3/data_collection/flow_processes`);
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, 'data_collection__flow_processes');
t.is(response.name, 'Flow Name');
t.is(response.permanentLink, 'flow_name');
});
/**
* @test {FlowService.insert}
*/
test('[unit] FlowService.insert should throw an error with an invalid token', async (t) => {
let request = {};
flowService.cacheMode = 'networkOnly';
nock(client.apiBaseUrl).post(`/v3/data_collection/flow_processes`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [422, {
errors: [
{
source: {
pointer: '/data/attributes/mobile_application_key'
},
detail: 'can\'t be blank'
}
]
}];
});
const requestJsonApi = {
data: {
type: 'data_collection/flow_processes',
attributes: {
push_id: 'FAKE_ID',
mobile_application_key: 'invalid'
}
}
};
client.mobileApplicationKey = 'invalid';
const flow = new Flow(requestJsonApi);
const response = await flowService.insert(flow).catch(err => err);
t.is(response.message, `"/data/attributes/mobile_application_key": can't be blank`);
});
// FlowService.update method
/**
* @test {FlowService.update}
*/
test.serial('[unit] FlowService.update should throw errors for invalid parameters', async (t) => {
client.authToken = undefined;
const undefinedError = 'FlowService.update error: requires authToken and flow is not defined';
await t.throws(() => flowService.update(), undefinedError);
});
// FlowService.update method
/**
* @test {FlowService.update}
*/
test('[unit] FlowService.update should successfully update a flow with a flow object', async (t) => {
const { patchResponse } = t.context;
const flowJsonApi = {
data: {
id: 6,
type: 'data_collection__flow_processes',
attributes: {
name: 'Updated',
description: 'Updated flow description',
permanent_link: 'dummy_77',
steps: []
}
}
};
const flow = new Flow(flowJsonApi);
let request = {};
client.reset();
client.authToken = 'valid_token';
nock(client.apiBaseUrl).patch(`/v3/data_collection/flow_processes/6`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, patchResponse];
});
const response = await flowService.update(flow);
t.is(request.path, `/v3/data_collection/flow_processes/6`);
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, flowJsonApi);
t.is(response.id, 6);
t.is(response.type, 'data_collection__flow_processes');
t.is(response.name, 'Updated');
t.is(response.description, 'Updated flow description');
t.is(response.permanentLink, 'dummy_77');
t.is(response.consentCredentials, null);
t.is(response.createdAt, '2018-08-19T22:03:19Z');
t.is(response.updatedAt, '2018-08-19T22:03:20Z');
t.is(response.ownerType, 'MobileUser');
t.is(response.publishedAt, null);
t.is(response.conditionalPaths, null);
t.is(response.steps.length, 0);
t.deepEqual(response.steps, []);
t.is(response.published, null);
t.is(response.draft, null);
t.is(response.first_step, null);
});