test/unit/services.user.v3.invitation-nock.js
import test from 'ava';
import nock from 'nock';
import {
client,
mobileUserService,
userService,
Device,
User,
} from '../../src';
test.before('start server', (t) => {
client.apiBaseUrl = 'https://somesite.Clinical6.com';
t.context.getInvitationResponse = {
data: {
id: 'invitationvalidation',
type: 'invitation_validations',
attributes: {
invitation_token: '59467032',
email: 'some@thing.com',
status: 'acceptable'
}
}
};
t.context.insertMobileUserResponse = {
data: {
id: '419',
type: 'mobile_users',
attributes: {
uuid: 'ff030b0a-2f04-4a2f-ab39-59c2c5744b22',
account_name: '25089567',
email: 'user631@fake.com',
created_at: '2018-02-14T16:39:05Z',
updated_at: '2018-02-14T16:39:05Z',
verified_at: null,
invitation_sent_at: '2018-02-14T16:39:05Z',
invitation_accepted_at: null,
disabled: false,
disabled_at: null
},
relationships: {
devices: {
data: []
},
user_role: {
data: {
id: '308',
type: 'user_roles'
}
},
profile: {
data: {
id: '650',
type: 'profiles'
}
},
language: {
data: {
id: '1',
type: 'languages'
}
},
patient: {
data: null
}
}
}
};
t.context.insertUserResponse = {
data: {
id: '171',
type: 'users',
attributes: {
uuid: 'b15686e7-8d9c-419e-8fe6-03fa4630fb2c',
email: 'test@test.com',
created_at: '2018-02-14T16:38:33Z',
updated_at: '2018-02-14T16:38:33Z',
invitation_sent_at: '2018-02-14T16:38:33Z',
invitation_accepted_at: null,
disabled_at: null
},
relationships: {
user_role: {
data: {
id: '227',
type: 'user_roles'
}
},
devices: {
data: []
},
profile: {
data: {
id: '492',
type: 'profiles'
}
}
}
}
};
t.context.updateMobileUserResponse = {
data: {
id: '10',
type: 'mobile_users',
attributes: {
uuid: 'b5a0d8e9-a988-4a29-aefb-22402f92d58e',
account_name: 'dummy_7',
email: 'user10@fake.com',
encryption_key: 'b00290b6e47e63dc7b221c64c0dc7fec',
created_at: '2017-08-14T22:55:11Z',
updated_at: '2017-08-14T22:55:11Z',
verified_at: null,
invitation_sent_at: null,
invitation_accepted_at: '2017-08-14T22:55:11Z'
},
relationships: {
devices: {
data: [
{
id: '4',
type: 'devices'
}
]
},
user_role: {
data: {
id: '10',
type: 'user_roles'
}
},
language: {
data: {
id: '4',
type: 'languages'
}
}
}
},
included: [
{
id: '4',
type: 'devices',
attributes: {
udid: 'ph2knq8xtg1znvuhrv0h',
technology: 'ios',
access_token: '05eaf798ce4bcce9e98ec01843af4881',
push_id: 'vmp6cl06avq3k2v6ij1z6hv0gaz5y47qx6aotwywq60buoy2sla2hmmulmpbte45',
created_at: '2017-08-14T22:55:11Z',
updated_at: '2017-08-14T22:55:11Z',
app_version: null
}
},
{
id: '10',
type: 'user_roles',
attributes: {
permanent_link: 'mobile',
name: 'Default Mobile',
is_super: false,
is_admin: false,
is_mobile: true,
is_default: true
}
}
]
};
t.context.updateUserResponse = {
data: {
id: '110',
type: 'users',
attributes: {
uuid: '09140540-e23f-4ccd-9f99-072fed4f07b3',
email: 'user326@fake.com',
created_at: '2018-02-22T19:47:25Z',
updated_at: '2018-02-22T19:47:25Z',
invitation_sent_at: '2018-02-22T19:47:25Z',
invitation_accepted_at: '2018-02-22T19:47:25Z',
disabled_at: null
},
relationships: {
user_role: {
data: {
id: '149',
type: 'user_roles'
}
},
devices: {
data: []
},
profile: {
data: {
id: '337',
type: 'profiles'
}
}
}
}
};
});
test.after('server shut down', () => {});
test.beforeEach((t) => {
client.cache = 'never';
client.authToken = 'valid_token';
t.context.storage = client.storageUtility;
t.context.mobileUserJsonInvite = {
data: {
type: 'invitations',
attributes: {
email: 'user633@fake.com'
},
relationships: {
language: {
data: {
type: 'languages',
id: 9
}
}
}
}
};
t.context.mobileUserJsonInviteWithSite = {
data: {
type: 'invitations',
attributes: {
email: 'user633@fake.com'
},
relationships: {
site: {
data: {
type: 'trials__sites',
id: 15
}
}
}
}
};
t.context.mobileUserJsonInviteWithDP = {
data: {
type: 'invitations',
attributes: {
email: 'user633@fake.com',
dynamic_profile: {
cookies: 52
}
}
}
};
t.context.adminUserJsonInvite = {
data: {
type: 'invitations',
attributes: {
email: 'test@test.com',
first_name: 'John',
last_name: 'Doe'
},
relationships: {
user_role: {
data: {
type: 'user_roles',
id: 227
}
}
}
}
};
});
// UserService.acceptInvitation method
/**
* @test {UserService.acceptInvitation}
*/
test('[unit] UserService.acceptInvitation should exist', (t) => {
t.truthy(mobileUserService.acceptInvitation);
});
/**
* @test {UserService.acceptInvitation}
*/
test('[unit] UserService.acceptInvitation should throw errors for invalid parameters', async (t) => {
const title = 'UserService.acceptInvitation error';
// undefined mobile user
await t.throwsAsync(mobileUserService.acceptInvitation(), `${title}: token is not defined`);
await t.throwsAsync(mobileUserService.acceptInvitation({}), `${title}: token is not a string`);
let token = 'valid_token';
await t.throwsAsync(mobileUserService.acceptInvitation(token, { device: {} }), `${title}: device does not have id`);
await t.throwsAsync(mobileUserService.acceptInvitation(token, { email: 'hello' }), `${title}: email is not a valid email`);
// undefined mobile user
token = undefined;
await t.throwsAsync(userService.acceptInvitation(), `${title}: token is not defined`);
await t.throwsAsync(userService.acceptInvitation({}), `${title}: token is not a string`);
token = 'valid_token';
await t.throwsAsync(userService.acceptInvitation(token, { device: {} }), `${title}: device does not have id`);
await t.throwsAsync(userService.acceptInvitation(token, { email: 'hello' }), `${title}: email is not a valid email`);
});
/**
* @test {UserService.acceptInvitation}
*/
test('[unit] UserService.acceptInvitation should successfully accept an invitation for a mobile user', async (t) => {
const { updateMobileUserResponse } = t.context;
let request = {};
nock(client.apiBaseUrl).patch(`/v3/mobile_users/invitation`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, updateMobileUserResponse];
});
const requestJsonApi = {
data: {
type: 'invitations',
attributes: {
invitation_token: '15886891',
password: `123456`
},
relationships: {
devices: {
data: {
type: 'devices',
id: 4
}
}
}
}
};
const device = new Device({ id: 4 });
device.store();
const response = await mobileUserService.acceptInvitation('15886891', { password: '123456', device });
t.is(request.path, `/v3/mobile_users/invitation`);
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.truthy(response);
t.is(response.constructor.name, 'User');
});
/**
* @test {UserService.acceptInvitation}
*/
test('[unit] UserService.acceptInvitation should successfully accept an invitation for a user', async (t) => {
const { updateUserResponse } = t.context;
let request = {};
nock(client.apiBaseUrl).patch(`/v3/users/invitation`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, updateUserResponse];
});
const requestJsonApi = {
data: {
type: 'invitations',
attributes: {
invitation_token: '15886891',
password: `123456`
},
relationships: {
devices: {
data: {
type: 'devices',
id: 4
}
}
}
}
};
const device = new Device({ id: 4 });
device.store();
const response = await userService.acceptInvitation('15886891', { password: '123456', device });
t.is(request.path, `/v3/users/invitation`);
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.truthy(response);
t.is(response.constructor.name, 'User');
});
// UserService.getInvitationStatus method
/**
* @test {UserService.getInvitationStatus}
*/
test.serial('[unit] UserService.getInvitationStatus should throw an error when there is no authToken', async (t) => {
client.authToken = undefined;
const title = `UserService.getInvitationStatus error`;
await t.throwsAsync(userService.getInvitationStatus(), `${title}: requires authToken and invitation_token is not defined`);
await t.throwsAsync(userService.getInvitationStatus(undefined, { invitation_token: 'asdf' }), `${title}: requires authToken`);
});
/**
* @test {UserService.getInvitationStatus}
*/
test('[unit] UserService.getInvitationStatus should successfully get the invitaiton status', async (t) => {
const { getInvitationResponse } = t.context;
let request = {};
nock(client.apiBaseUrl).post(`/v3/mobile_users/invitation/status`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [201, getInvitationResponse];
});
const requestJsonApi = {
data: {
type: 'invitations',
attributes: {
invitation_token: '59467032',
email: 'some@thing.com'
}
}
};
const user = new User({ email: 'some@thing.com' });
user.type = 'mobile_users';
const response = await mobileUserService.getInvitationStatus(user, { invitation_token: '59467032' });
t.is(request.path, `/v3/mobile_users/invitation/status`);
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, 'invitationvalidation');
t.is(response.type, 'invitation_validations');
t.is(response.invitationToken, '59467032');
t.is(response.email, 'some@thing.com');
});
// // SiteService.update method
// /**
// * @test {Clinical6.update}
// */
// test.serial('[unit] SiteService.update should throw an error when there is no authToken', async (t) => {
// client.authToken = undefined;
// const title = `SiteService.update error`;
// await t.throwsAsync(clinical6.update(new Site({ id: 5 })), `${title}: requires authToken`);
// });
// /**
// * @test {Clinical6.update}
// */
// test('[unit] SiteService.update should successfully update a site with a site object', async (t) => {
// const { site, updateResponse, siteJsonApi } = t.context;
// new Location({ id: 117 }).store();
// let request = {};
// nock(client.apiBaseUrl).patch(`/v3/mobile_users/invitation/status/${site.id}`).reply(function (uri, requestBody) {
// request = this.req;
// request.requestBody = requestBody;
// return [200, updateResponse];
// });
// const response = await clinical6.update(site);
// t.is(request.path, `/v3/mobile_users/invitation/status/${site.id}`);
// t.is(request.headers.accept, 'application/json');
// t.deepEqual(request.requestBody, siteJsonApi);
// t.is(request.headers['content-type'], 'application/json');
// t.is(request.headers.authorization, 'Token token=valid_token');
// t.is(response.id, 18);
// t.is(response.type, 'trials__sites');
// });