test/unit/services.user.v3.mobile.js
import test from 'ava';
import nock from 'nock';
import {
client,
clinical6,
mobileUserService,
AvailableStrategy,
AwardedBadge,
Badge,
CohortAssignment,
ConsentGrant,
Consultation,
Device,
EntryGroup,
Role,
Rule,
Schedule,
User,
} from '../../src';
test.before('start server', (t) => {
client.apiBaseUrl = 'https://somesite.Clinical6.com';
t.context.getResponseGrants454 = {
data: [
{
id: 3,
type: 'consent__grants',
attributes: {
document: {
url: '/uploads/test/consent/grant/document/3/1.pdf'
},
progress: 'all_signed',
created_at: '2018-07-20T13:32:51Z',
updated_at: '2018-07-20T13:32:51Z'
},
relationships: {
granted_for: {
data: {
id: 454,
type: 'mobile_users'
}
},
granted_by: {
data: {
id: 454,
type: 'mobile_users'
}
},
strategy: {
data: {
id: 62,
type: 'consent__strategies'
}
},
form_version: {
data: null
},
agreement: {
data: null
}
}
},
{
id: 4,
type: 'consent__grants',
attributes: {
sign_url: null,
progress: 'all_signed',
created_at: '2018-07-20T13:32:51Z',
updated_at: '2018-07-20T13:32:51Z'
},
relationships: {
granted_for: {
data: {
id: 454,
type: 'mobile_users'
}
},
granted_by: {
data: {
id: 454,
type: 'mobile_users'
}
},
strategy: {
data: {
id: 63,
type: 'consent__strategies'
}
},
form_version: {
data: {
id: 37,
type: 'consent__form_versions'
}
},
agreement: {
data: {
id: 18,
type: 'agreement__agreements'
}
}
}
}
],
included: [
{
id: 62,
type: 'consent__strategies',
attributes: {
name: 'Strategy-67',
strategy_type: 'paper',
created_at: '2018-07-20T13:32:51Z',
updated_at: '2018-07-20T13:32:51Z'
},
relationships: {
cohort: {
data: {
id: 105,
type: 'cohorts'
}
},
forms: {
data: []
}
}
},
{
id: 63,
type: 'consent__strategies',
attributes: {
name: 'Strategy-68',
strategy_type: 'electronic',
created_at: '2018-07-20T13:32:51Z',
updated_at: '2018-07-20T13:32:51Z'
},
relationships: {
cohort: {
data: {
id: 106,
type: 'cohorts'
}
},
forms: {
data: [
{
id: 51,
type: 'consent__forms'
}
]
}
}
},
{
id: 37,
type: 'consent__form_versions',
attributes: {
archived_at: null
},
relationships: {
site: {
data: {
id: 115,
type: 'trials__sites'
}
},
agreement_template: {
data: {
id: 102,
type: 'agreement__templates'
}
},
language: {
data: {
id: 63,
type: 'languages'
}
},
consent_form: {
data: {
id: 51,
type: 'consent__forms'
}
},
approver_groups: {
data: []
},
approvers: {
data: []
}
}
},
{
id: 51,
type: 'consent__forms',
attributes: {
enabled: true,
name: 'Form 54',
created_at: '2018-07-20T13:32:51Z',
updated_at: '2018-07-20T13:32:51Z'
},
relationships: {
consent_form_versions: {
data: [
{
id: 37,
type: 'consent__form_versions'
}
]
},
strategy: {
data: {
id: 63,
type: 'consent__strategies'
}
}
}
}
],
links: {},
meta: {
total_records: 2,
total_pages: 1
}
};
t.context.getResponse = {
data: [
{
id: '1',
type: 'mobile_users',
attributes: {
udid: 'this-is-a-udid-string',
technology: 'ios',
access_token: 'cd68fa04e458d6d1a9d29faec6a329d3',
push_id: null,
created_at: '2017-05-19T17:21:26.311Z',
updated_at: '2017-05-19T17:21:26.311Z',
app_version: null
}
},
{
id: '2',
type: 'mobile_users',
attributes: {
udid: 'this-is-a-udid-string',
technology: 'ios',
access_token: 'cd68fa04e458d6d1a9d29faec6a329d3',
push_id: null,
created_at: '2017-05-19T17:21:26.311Z',
updated_at: '2017-05-19T17:21:26.311Z',
app_version: null
}
}
]
};
t.context.getResponse2 = {
data: {
id: '2',
type: 'mobile_users',
attributes: {
uuid: 'dddb2ab3-3be9-4a54-8c2c-7687c4ec9bee',
account_name: '5nl1xkjc',
username: '5nl1xkjc',
email: null,
encryption_key: null,
created_at: '2017-05-15T19:08:17.076Z',
updated_at: '2017-05-15T19:08:17.108Z',
verified_at: null,
invitation_sent_at: null,
invitation_accepted_at: null
},
relationships: {
devices: {
data: [
{
id: '1',
type: 'devices'
}
]
}
}
},
included: [
{
id: '1',
type: 'devices',
attributes: {
udid: '660y6gb90yxlctukngk6',
technology: 'ios',
access_token: '4756992a843a504d2f786380b4a67760',
push_id: 'tsg6mrcgrto71iyi6bt113d1d72x68koo0e22fkd0e3rppztbn40va32qyj98prq',
created_at: '2017-05-15T19:08:16.000Z',
updated_at: '2017-05-15T19:08:17.000Z',
app_version: null
}
}
]
};
t.context.getResponseStrategies77 = {
data: [
{
id: 7,
type: 'consent__available_strategies',
relationships: {
strategy: {
data: {
id: 7,
type: 'consent__strategies'
}
},
forms: {
data: [
{
id: 5,
type: 'consent__forms'
},
{
id: 6,
type: 'consent__forms'
}
]
}
}
},
{
id: 8,
type: 'consent__available_strategies',
relationships: {
strategy: {
data: {
id: 8,
type: 'consent__strategies'
}
},
forms: {
data: null
}
}
}
],
included: [
{
id: 7,
type: 'consent__strategies',
attributes: {
name: 'Strategy-8',
strategy_type: 'electronic',
created_at: '2018-07-16T23:08:26Z',
updated_at: '2018-07-16T23:08:26Z'
},
relationships: {
cohort: {
data: {
id: 9,
type: 'cohorts'
}
},
forms: {
data: [
{
id: 5,
type: 'consent__forms'
},
{
id: 6,
type: 'consent__forms'
}
]
}
}
},
{
id: 5,
type: 'consent__forms',
attributes: {
enabled: true,
name: 'Form 5',
created_at: '2018-07-16T23:08:26Z',
updated_at: '2018-07-16T23:08:26Z'
},
relationships: {
consent_form_versions: {
data: [
{
id: 5,
type: 'consent__form_versions'
},
{
id: 6,
type: 'consent__form_versions'
}
]
},
strategy: {
data: {
id: 7,
type: 'consent__strategies'
}
}
}
},
{
id: 6,
type: 'consent__forms',
attributes: {
enabled: true,
name: 'Form 6',
created_at: '2018-07-16T23:08:26Z',
updated_at: '2018-07-16T23:08:26Z'
},
relationships: {
consent_form_versions: {
data: [
{
id: 7,
type: 'consent__form_versions'
}
]
},
strategy: {
data: {
id: 7,
type: 'consent__strategies'
}
}
}
},
{
id: 8,
type: 'consent__strategies',
attributes: {
name: 'Strategy-9',
strategy_type: 'waived',
created_at: '2018-07-16T23:08:26Z',
updated_at: '2018-07-16T23:08:26Z'
},
relationships: {
cohort: {
data: {
id: 9,
type: 'cohorts'
}
},
forms: {
data: []
}
}
}
]
};
t.context.getResponseAssignments80 = {
data: [
{
id: '6',
type: 'cohort_assignments',
attributes: {
created_at: '2018-04-25T17:44:57Z',
updated_at: '2018-04-25T17:44:57Z'
},
relationships: {
user: {
data: {
id: '80',
type: 'mobile_users'
}
},
cohort: {
data: {
id: '22',
type: 'cohorts'
}
}
}
},
{
id: '7',
type: 'cohort_assignments',
attributes: {
created_at: '2018-04-25T17:44:57Z',
updated_at: '2018-04-25T17:44:57Z'
},
relationships: {
user: {
data: {
id: '80',
type: 'mobile_users'
}
},
cohort: {
data: {
id: '23',
type: 'cohorts'
}
}
}
},
{
id: '8',
type: 'cohort_assignments',
attributes: {
created_at: '2018-04-25T17:44:57Z',
updated_at: '2018-04-25T17:44:57Z'
},
relationships: {
user: {
data: {
id: '80',
type: 'mobile_users'
}
},
cohort: {
data: {
id: '24',
type: 'cohorts'
}
}
}
}
],
included: [
{
id: '22',
type: 'cohorts',
attributes: {
name: 'name-22',
cohort_type: 'static',
created_at: '2018-04-25T17:44:57Z',
updated_at: '2018-04-25T17:44:57Z'
}
},
{
id: '23',
type: 'cohorts',
attributes: {
name: 'name-23',
cohort_type: 'static',
created_at: '2018-04-25T17:44:57Z',
updated_at: '2018-04-25T17:44:57Z'
}
},
{
id: '24',
type: 'cohorts',
attributes: {
name: 'name-24',
cohort_type: 'static',
created_at: '2018-04-25T17:44:57Z',
updated_at: '2018-04-25T17:44:57Z'
}
}
]
};
t.context.getResponseConfirmRegistration = {
data: {
id: '196',
type: 'mobile_users',
attributes: {
uuid: '7cc2ae4d-580e-4bf5-84d6-0a32dd97f231',
account_name: 'dummy_178',
email: 'user273@fake.com',
encryption_key: null,
created_at: '2017-06-07T23:58:58Z',
updated_at: '2017-06-07T23:58:58Z',
disabled_at: '2017-06-07T23:58:58Z',
verified_at: null,
invitation_sent_at: null,
invitation_accepted_at: null
},
relationships: {
devices: {
data: [
{
id: '110',
type: 'devices'
}
]
}
}
}
};
t.context.getResponseConsultation = {
data: [
{
id: '4',
type: 'video_consultations',
attributes: {
name: 'General Consultation',
start_at: '2018-08-09T19:11:32Z',
end_at: null,
status: null,
session_identity: null,
confirmed_at: null,
deleted_at: null,
created_at: '2018-08-09T19:13:05Z',
updated_at: '2018-08-09T19:13:05Z'
},
relationships: {
video_consultation_participants: {
data: [
{
id: '2',
type: 'video_consultation_participants'
}
]
}
}
},
{
id: '5',
type: 'video_consultations',
attributes: {
name: 'General Consultation',
start_at: '2018-08-09T19:11:32Z',
end_at: null,
status: null,
session_identity: null,
confirmed_at: null,
deleted_at: null,
created_at: '2018-08-09T19:13:05Z',
updated_at: '2018-08-09T19:13:05Z'
},
relationships: {
video_consultation_participants: {
data: [
{
id: '3',
type: 'video_consultation_participants'
}
]
}
}
},
{
id: '6',
type: 'video_consultations',
attributes: {
name: 'General Consultation',
start_at: '2018-08-09T19:11:32Z',
end_at: null,
status: null,
session_identity: null,
confirmed_at: null,
deleted_at: null,
created_at: '2018-08-09T19:13:05Z',
updated_at: '2018-08-09T19:13:05Z'
},
relationships: {
video_consultation_participants: {
data: [
{
id: '4',
type: 'video_consultation_participants'
}
]
}
}
}
],
included: [
{
id: '2',
type: 'video_consultation_participants',
attributes: {
created_at: '2018-08-09T19:13:05Z',
updated_at: '2018-08-09T19:13:05Z'
},
relationships: {
video_consultation: {
data: {
id: '4',
type: 'video_consultations'
}
},
participant: {
data: {
id: '217',
type: 'mobile_users'
}
}
}
},
{
id: '3',
type: 'video_consultation_participants',
attributes: {
created_at: '2018-08-09T19:13:05Z',
updated_at: '2018-08-09T19:13:05Z'
},
relationships: {
video_consultation: {
data: {
id: '5',
type: 'video_consultations'
}
},
participant: {
data: {
id: '217',
type: 'mobile_users'
}
}
}
},
{
id: '4',
type: 'video_consultation_participants',
attributes: {
created_at: '2018-08-09T19:13:05Z',
updated_at: '2018-08-09T19:13:05Z'
},
relationships: {
video_consultation: {
data: {
id: '6',
type: 'video_consultations'
}
},
participant: {
data: {
id: '217',
type: 'mobile_users'
}
}
}
}
]
};
t.context.getResponseEntries45 = {
data: [
{
id: '1',
type: 'ediary__entries',
attributes: {
created_at: '2017-06-20T17:55:12Z',
updated_at: '2017-06-20T17:55:12Z',
date: '2018-06-02'
},
relationships: {
entry_group: {
data: {
id: '6',
type: 'ediary__entry_groups'
}
},
flow_process: {
data: {
id: '42',
type: 'data_collection__flow_processes'
}
},
captured_value_group: {
data: null
},
owner: {
data: {
id: '45',
type: 'mobile_users'
}
}
}
},
{
id: '2',
type: 'ediary__entries',
attributes: {
created_at: '2017-06-20T17:55:12Z',
updated_at: '2017-06-20T17:55:12Z',
date: '2018-06-02'
},
relationships: {
entry_group: {
data: {
id: '7',
type: 'ediary__entry_groups'
}
},
flow_process: {
data: {
id: '43',
type: 'data_collection__flow_processes'
}
},
captured_value_group: {
data: null
},
owner: {
data: {
id: '45',
type: 'mobile_users'
}
}
}
}
],
included: [
{
id: '6',
type: 'ediary__entry_groups',
attributes: {
name: 'dummy_378',
permanent_link: 'dummy_379',
position: 1,
category: null,
created_at: '2017-06-20T17:55:11Z',
updated_at: '2017-06-20T17:55:11Z'
},
relationships: {
ediary_entries: {
data: [
{
id: '1',
type: 'ediary__entries'
}
]
},
entry_templates: {
data: []
},
child_entry_groups: {
data: []
},
parent_entry_group: {
data: null
}
}
},
{
id: '42',
type: 'data_collection__flow_processes',
attributes: {
name: 'ipsa',
permanent_link: 'dummy_380',
consent_credentials: null,
created_at: '2017-06-20T17:55:12Z',
updated_at: '2017-06-20T17:55:12Z',
owner_type: 'User',
published_at: null,
conditional_paths: null
},
relationships: {
linked_steps: {
data: []
},
published: {
data: null
},
draft: {
data: null
},
initial_step: {
data: null
}
}
},
{
id: '45',
type: 'mobile_users',
attributes: {
uuid: '2017a89e-387f-410b-93f2-162e990c92db',
account_name: 'dummy_45',
email: 'user84@fake.com',
encryption_key: null,
created_at: '2017-06-20T17:55:11Z',
updated_at: '2017-06-20T17:55:12Z',
verified_at: null,
invitation_sent_at: null,
invitation_accepted_at: null
},
relationships: {
devices: {
data: []
}
}
},
{
id: '7',
type: 'ediary__entry_groups',
attributes: {
name: 'dummy_381',
permanent_link: 'dummy_382',
position: 2,
category: null,
created_at: '2017-06-20T17:55:12Z',
updated_at: '2017-06-20T17:55:12Z'
},
relationships: {
ediary_entries: {
data: [
{
id: '2',
type: 'ediary__entries'
}
]
},
entry_templates: {
data: []
},
child_entry_groups: {
data: []
},
parent_entry_group: {
data: null
}
}
},
{
id: '43',
type: 'data_collection__flow_processes',
attributes: {
name: 'ipsa',
permanent_link: 'dummy_383',
consent_credentials: null,
created_at: '2017-06-20T17:55:12Z',
updated_at: '2017-06-20T17:55:12Z',
owner_type: 'User',
published_at: null,
conditional_paths: null
},
relationships: {
linked_steps: {
data: []
},
published: {
data: null
},
draft: {
data: null
},
initial_step: {
data: null
}
}
}
]
};
t.context.getResponseSchedules = {
data: [
{
id: '1',
type: 'scheduler__personalized_rule_schedules',
attributes: {
start_date: '2017-09-10',
end_date: '2017-09-27',
time: '10:00',
timezone: 'UTC',
relative_schedule: null,
days_of_week: '0,1,2,3,4,5,6',
relative_unit: null,
start_date_offset: 0,
start_date_offset_unit: null,
skip_exceptions: false,
enabled: true,
exception_days: null,
active_time_start: null,
active_time_end: null
},
relationships: {
mobile_user: {
data: {
id: '72',
type: 'mobile_users'
}
},
scheduleable: {
data: {
id: '1',
type: 'reminder__rules'
}
}
}
},
{
id: '2',
type: 'scheduler__personalized_rule_schedules',
attributes: {
start_date: '2017-09-10',
end_date: '2017-09-27',
time: '10:00',
timezone: 'UTC',
relative_schedule: null,
days_of_week: '0,1,2,3,4,5,6',
relative_unit: null,
start_date_offset: 0,
start_date_offset_unit: null,
skip_exceptions: false,
enabled: true,
exception_days: null,
active_time_start: null,
active_time_end: null
},
relationships: {
mobile_user: {
data: {
id: '72',
type: 'mobile_users'
}
},
scheduleable: {
data: {
id: '2',
type: 'reminder__rules'
}
}
}
},
{
id: '3',
type: 'scheduler__personalized_rule_schedules',
attributes: {
start_date: '2017-09-10',
end_date: '2017-09-27',
time: '10:00',
timezone: 'UTC',
relative_schedule: null,
days_of_week: '0,1,2,3,4,5,6',
relative_unit: null,
start_date_offset: 0,
start_date_offset_unit: null,
skip_exceptions: false,
enabled: true,
exception_days: null,
active_time_start: null,
active_time_end: null
},
relationships: {
mobile_user: {
data: {
id: '72',
type: 'mobile_users'
}
},
scheduleable: {
data: {
id: '3',
type: 'reminder__rules'
}
}
}
}
],
included: [
{
id: '1',
type: 'reminder__rules',
attributes: {
permanent_link: 'dummy_274',
label: null,
created_at: '2017-09-12T05:36:25Z',
updated_at: '2017-09-12T05:36:25Z'
}
},
{
id: '2',
type: 'reminder__rules',
attributes: {
permanent_link: 'dummy_275',
label: null,
created_at: '2017-09-12T05:36:25Z',
updated_at: '2017-09-12T05:36:25Z'
}
},
{
id: '3',
type: 'reminder__rules',
attributes: {
permanent_link: 'dummy_276',
label: null,
created_at: '2017-09-12T05:36:25Z',
updated_at: '2017-09-12T05:36:25Z'
}
}
]
};
t.context.deleteRequestMobileUser = {
data: {
id: '1',
type: 'mobile_users',
attributes: {
account_name: '5nl1xkjc',
username: '5nl1xkjc',
created_at: '2017-05-15T19:08:17.076Z',
email: null,
encryption_key: null,
updated_at: '2017-05-15T19:08:17.108Z',
uuid: 'dddb2ab3-3be9-4a54-8c2c-7687c4ec9bee',
verified_at: null,
invitation_sent_at: null,
invitation_accepted_at: null
},
relationships: {
devices: {
data: [
{
id: '1',
type: 'devices'
}
]
}
}
},
included: [
{
id: '1',
type: 'devices',
attributes: {
udid: '660y6gb90yxlctukngk6',
technology: 'ios',
access_token: '4756992a843a504d2f786380b4a67760',
push_id: 'tsg6mrcgrto71iyi6bt113d1d72x68koo0e22fkd0e3rppztbn40va32qyj98prq',
created_at: '2017-05-15T19:08:16.000Z',
updated_at: '2017-05-15T19:08:17.000Z',
app_version: null
}
}
]
};
t.context.insertResponseAwardBadge39 = {
data: {
id: '32',
type: 'awarded_badges',
attributes: {
created_at: '2017-08-10T17:54:18Z',
updated_at: '2017-08-10T17:54:18Z',
count: 0,
earned_on_date: null
},
relationships: {
awardee: {
data: {
type: 'mobile_users',
id: '486'
}
},
badge: {
data: {
type: 'badges',
id: '39'
}
}
}
},
included: [
{
id: '39',
type: 'badges',
attributes: {
created_at: '2017-08-09T16:23:56Z',
updated_at: '2017-08-09T16:23:56Z',
title: 'dummy_462',
description: 'Demo Content info...',
redemption_points: 250,
image: {
image: {
url: '/uploads/test/reward/image/17/1.png',
small: {
url: '/uploads/test/reward/image/17/small_1.png'
},
small_hd: {
url: '/uploads/test/reward/image/17/small_hd_1.png'
},
fullscreen: {
url: '/uploads/test/reward/image/17/fullscreen_1.png'
},
main: {
url: '/uploads/test/reward/image/17/main_1.png'
},
fullscreen_hd: {
url: '/uploads/test/reward/image/17/fullscreen_hd_1.png'
},
main_hd: {
url: '/uploads/test/reward/image/17/main_hd_1.png'
}
}
},
position: 1,
enabled: true,
featured: null,
based_on: null,
threshold: null,
time_unit: null,
start_point: null,
start_at: null,
disabled_image: {
disabled_image: {
url: '/default/default.png',
small: {
url: '/default/small_default.png'
},
small_hd: {
url: '/default/small_hd_default.png'
},
fullscreen: {
url: '/default/fullscreen_default.png'
},
main: {
url: '/default/main_default.png'
},
fullscreen_hd: {
url: '/default/fullscreen_hd_default.png'
},
main_hd: {
url: '/default/main_hd_default.png'
}
}
},
cache_token: 'xMnLvzU_uu4'
}
}
]
};
t.context.insertResponseEntries53 = {
data: {
id: '7',
type: 'ediary__entries',
attributes: {
created_at: '2017-06-27T20:32:07Z',
updated_at: '2017-06-27T20:32:07Z',
date: '2018-06-02'
},
relationships: {
entry_group: {
data: {
id: '8',
type: 'ediary__entry_groups'
}
},
template: {
data: {
id: '7',
type: 'ediary__entry_templates'
}
},
captured_value_group: {
data: null
},
owner: {
data: {
id: '22',
type: 'mobile_users'
}
},
status: {
data: null
}
}
},
included: [
{
id: '7',
type: 'ediary__entry_templates',
attributes: {
category: 'automatic',
created_at: '2017-06-27T20:32:07Z',
updated_at: '2017-06-27T20:32:07Z'
},
relationships: {
entry_group: {
data: {
id: '8',
type: 'ediary__entry_groups'
}
},
flow_process: {
data: {
id: '23',
type: 'data_collection__flow_processes'
}
}
}
},
{
id: '22',
type: 'mobile_users',
attributes: {
uuid: '51edc9a9-6e07-4ffd-a22a-8a620f45ac99',
account_name: 'dummy_21',
email: 'user55@fake.com',
encryption_key: null,
created_at: '2017-06-27T20:32:07Z',
updated_at: '2017-06-27T20:32:07Z',
verified_at: null,
invitation_sent_at: null,
invitation_accepted_at: null
},
relationships: {
devices: {
data: []
}
}
},
{
id: '8',
type: 'ediary__entry_groups',
attributes: {
name: 'dummy_3781',
permanent_link: 'dummy_3791',
position: 1,
category: null,
created_at: '2017-06-20T17:55:11Z',
updated_at: '2017-06-20T17:55:11Z'
},
relationships: {
ediary_entries: {
data: [
{
id: '7',
type: 'ediary__entries'
}
]
},
entry_templates: {
data: []
},
child_entry_groups: {
data: []
},
parent_entry_group: {
data: null
}
}
}
]
};
t.context.insertResponseMobileUser = {
data: {
id: '1',
type: 'mobile_users',
attributes: {
account_name: '5nl1xkjc',
username: '5nl1xkjc',
created_at: '2017-05-15T19:08:17.076Z',
email: null,
encryption_key: null,
updated_at: '2017-05-15T19:08:17.108Z',
uuid: 'dddb2ab3-3be9-4a54-8c2c-7687c4ec9bee',
verified_at: null,
invitation_sent_at: null,
invitation_accepted_at: null
},
relationships: {
devices: {
data: [
{
id: '1',
type: 'devices'
}
]
}
}
},
included: [
{
id: '1',
type: 'devices',
attributes: {
udid: '660y6gb90yxlctukngk6',
technology: 'ios',
access_token: '4756992a843a504d2f786380b4a67760',
push_id: 'tsg6mrcgrto71iyi6bt113d1d72x68koo0e22fkd0e3rppztbn40va32qyj98prq',
created_at: '2017-05-15T19:08:16.000Z',
updated_at: '2017-05-15T19:08:17.000Z',
app_version: null
}
}
]
};
t.context.insertRequestMobileUser = {
data: {
type: 'mobile_users',
attributes: {
account_name: '5nl1xkjc',
username: '5nl1xkjc',
created_at: '2017-05-15T19:08:17.076Z',
email: null,
encryption_key: null,
updated_at: '2017-05-15T19:08:17.108Z',
uuid: 'dddb2ab3-3be9-4a54-8c2c-7687c4ec9bee',
verified_at: null,
invitation_sent_at: null,
invitation_accepted_at: null
}
}
};
t.context.updateResponseMobileUser = {
data: {
id: 1,
type: 'mobile_users',
attributes: {
account_name: '5nl1xkjc',
username: '5nl1xkjc',
created_at: '2017-05-15T19:08:17.076Z',
email: null,
encryption_key: null,
updated_at: '2017-05-15T19:08:17.108Z',
uuid: 'dddb2ab3-3be9-4a54-8c2c-7687c4ec9bee',
verified_at: null,
invitation_sent_at: null,
invitation_accepted_at: null
}
}
};
t.context.updateResponseMobileUser9 = {
data: {
id: 9,
type: 'mobile_users',
attributes: {
uuid: '6234e115-b9b4-44ae-aa8a-66b8f04d4f0e',
email: 'user1@fake.com',
created_at: '2018-02-27T13:41:00Z',
updated_at: '2018-02-28T04:44:14Z',
invitation_sent_at: null,
invitation_accepted_at: null,
disabled_at: null,
access_locked: false
},
relationships: {
user_role: {
data: {
id: 1,
type: 'user_roles'
}
},
devices: {
data: []
},
profile: {
data: {
id: 6,
type: 'profiles'
}
}
}
},
included: [
{
id: 1,
type: 'user_roles',
attributes: {
permanent_link: 'admin',
name: 'Admin',
is_super: false,
is_admin: true,
is_mobile: false,
is_default: false
}
},
{
id: 6,
type: 'profiles',
attributes: {
created_at: '2018-02-27T13:41:00Z',
updated_at: '2018-02-27T13:41:00Z',
first_name: 'Molly',
middle_initial: null,
last_name: 'Cartwright',
prefix: null,
suffix: null,
gender: 'male',
ethnicity: '',
occupation: null,
avatar: {
url: '/uploads/development/profile/avatar/6/d1946007ee44d672e4eb2390ce9cad8bf15b7bac.png',
small: {
url: '/uploads/development/profile/avatar/6/small_d1946007ee44d672e4eb2390ce9cad8bf15b7bac.png'
},
main: {
url: '/uploads/development/profile/avatar/6/main_d1946007ee44d672e4eb2390ce9cad8bf15b7bac.png'
},
thumb: {
url: '/uploads/development/profile/avatar/6/thumb_d1946007ee44d672e4eb2390ce9cad8bf15b7bac.png'
}
},
username: null,
dob: null,
timezone: 'UTC',
phone: null,
email: 'user1@fake.com',
age: 28,
language: {
id: 1,
iso: 'en',
name: 'English',
created_at: '2018-02-14T15:43:25Z',
updated_at: '2018-02-14T15:43:25Z',
is_default: true,
image: {
url: '/assets/default/default-16daaa70b849a969f5ab41d3b7c9513c8ca890a6dd3b30e39c5afc25b8a773b6.png',
thumb: {
url: '/assets/default/thumb_default-80b0cfa7e6bd6ee57d0f3806eb25b31a842fe9ab69fc4a594303f5555b5bc4bd.png'
}
}
}
},
relationships: {
profileable: {
data: {
id: 4,
type: 'users'
}
}
}
}
]
};
t.context.updateResponseResetPassword = {
data: {
id: '32',
type: 'mobile_users',
attributes: {
uuid: 'my-special-uuid',
account_name: '47926633',
email: 'myEmail@email.com',
created_at: '2018-04-16T16:32:36Z',
updated_at: '2018-04-25T22:04:55Z',
invitation_sent_at: '2018-04-16T16:32:36Z',
invitation_accepted_at: '2018-04-16T16:36:17Z',
disabled: false,
disabled_at: null
},
relationships: {
devices: {
data: [
{
id: '81',
type: 'devices'
},
{
id: '91',
type: 'devices'
},
{
id: '93',
type: 'devices'
},
{
id: '95',
type: 'devices'
},
{
id: '100',
type: 'devices'
},
{
id: '101',
type: 'devices'
},
{
id: '104',
type: 'devices'
},
{
id: '114',
type: 'devices'
},
{
id: '117',
type: 'devices'
},
{
id: '124',
type: 'devices'
},
{
id: '134',
type: 'devices'
},
{
id: '148',
type: 'devices'
},
{
id: '258',
type: 'devices'
},
{
id: '259',
type: 'devices'
},
{
id: '262',
type: 'devices'
},
{
id: '264',
type: 'devices'
},
{
id: '267',
type: 'devices'
},
{
id: '368',
type: 'devices'
},
{
id: '369',
type: 'devices'
},
{
id: '371',
type: 'devices'
},
{
id: '375',
type: 'devices'
}
]
},
user_role: {
data: {
id: '8',
type: 'user_roles'
}
},
profile: {
data: {
id: '96',
type: 'profiles'
}
},
language: {
data: {
id: '1',
type: 'languages'
}
},
patient: {
data: {
id: '17',
type: 'trials__site_members'
}
},
threads: {
data: []
}
}
},
included: [
{
id: '81',
type: 'devices',
attributes: {
udid: 'android-device-udid',
technology: 'android',
access_token: 'android-token-81',
push_id: null,
created_at: '2018-04-16T16:35:53Z',
updated_at: '2018-04-16T16:36:17Z',
app_version: null
}
},
{
id: '91',
type: 'devices',
attributes: {
udid: 'android-device-udid',
technology: 'android',
access_token: 'android-token-91',
push_id: null,
created_at: '2018-04-16T18:12:04Z',
updated_at: '2018-04-16T18:12:15Z',
app_version: null
}
},
{
id: '93',
type: 'devices',
attributes: {
udid: 'android-device-udid',
technology: 'android',
access_token: 'android-token-93',
push_id: null,
created_at: '2018-04-16T18:17:01Z',
updated_at: '2018-04-16T18:17:06Z',
app_version: null
}
},
{
id: '95',
type: 'devices',
attributes: {
udid: 'android-device-udid',
technology: 'android',
access_token: 'android-token-95',
push_id: null,
created_at: '2018-04-16T18:21:54Z',
updated_at: '2018-04-16T18:21:56Z',
app_version: null
}
},
{
id: '100',
type: 'devices',
attributes: {
udid: null,
technology: null,
access_token: '???-token-100',
push_id: null,
created_at: '2018-04-16T18:37:19Z',
updated_at: '2018-04-16T18:37:21Z',
app_version: null
}
},
{
id: '101',
type: 'devices',
attributes: {
udid: 'android-device-udid',
technology: 'android',
access_token: 'android-token-101',
push_id: null,
created_at: '2018-04-16T18:52:08Z',
updated_at: '2018-04-16T18:52:10Z',
app_version: null
}
},
{
id: '104',
type: 'devices',
attributes: {
udid: 'b0bddcf93bf3638b',
technology: 'android',
access_token: 'android-token-104',
push_id: null,
created_at: '2018-04-16T19:07:13Z',
updated_at: '2018-04-16T19:07:20Z',
app_version: null
}
},
{
id: '114',
type: 'devices',
attributes: {
udid: 'android-device-udid',
technology: 'android',
access_token: 'android-token-114',
push_id: null,
created_at: '2018-04-17T00:15:21Z',
updated_at: '2018-04-17T00:15:48Z',
app_version: null
}
},
{
id: '117',
type: 'devices',
attributes: {
udid: 'android-device-udid',
technology: 'android',
access_token: 'android-token-117',
push_id: null,
created_at: '2018-04-17T00:25:18Z',
updated_at: '2018-04-17T00:26:01Z',
app_version: null
}
},
{
id: '124',
type: 'devices',
attributes: {
udid: 'android-device-udid',
technology: 'android',
access_token: 'android-token-124',
push_id: null,
created_at: '2018-04-17T18:36:28Z',
updated_at: '2018-04-17T18:36:36Z',
app_version: null
}
},
{
id: '134',
type: 'devices',
attributes: {
udid: null,
technology: null,
access_token: '???-token-134',
push_id: null,
created_at: '2018-04-17T22:46:25Z',
updated_at: '2018-04-17T22:46:32Z',
app_version: null
}
},
{
id: '148',
type: 'devices',
attributes: {
udid: null,
technology: null,
access_token: '???-token-148',
push_id: null,
created_at: '2018-04-18T21:39:12Z',
updated_at: '2018-04-18T21:39:24Z',
app_version: null
}
},
{
id: '258',
type: 'devices',
attributes: {
udid: 'android-device-udid',
technology: 'android',
access_token: 'android-token-258',
push_id: null,
created_at: '2018-04-25T03:41:40Z',
updated_at: '2018-04-25T03:41:41Z',
app_version: null
}
},
{
id: '259',
type: 'devices',
attributes: {
udid: 'android-device-udid',
technology: 'android',
access_token: 'android-token-259',
push_id: null,
created_at: '2018-04-25T03:44:32Z',
updated_at: '2018-04-25T03:44:49Z',
app_version: null
}
},
{
id: '262',
type: 'devices',
attributes: {
udid: 'android-device-udid',
technology: 'android',
access_token: 'android-token-262',
push_id: null,
created_at: '2018-04-25T03:48:20Z',
updated_at: '2018-04-25T03:48:21Z',
app_version: null
}
},
{
id: '264',
type: 'devices',
attributes: {
udid: 'android-device-udid',
technology: 'android',
access_token: 'android-token-264',
push_id: null,
created_at: '2018-04-25T03:57:13Z',
updated_at: '2018-04-25T03:57:14Z',
app_version: null
}
},
{
id: '267',
type: 'devices',
attributes: {
udid: 'android-device-udid',
technology: 'android',
access_token: 'android-token-267',
push_id: null,
created_at: '2018-04-25T04:00:23Z',
updated_at: '2018-04-25T04:00:24Z',
app_version: null
}
},
{
id: '368',
type: 'devices',
attributes: {
udid: 'ios-device-udid',
technology: 'ios',
access_token: 'ios-token-368',
push_id: null,
created_at: '2018-04-25T21:49:41Z',
updated_at: '2018-04-25T21:49:41Z',
app_version: null
}
},
{
id: '369',
type: 'devices',
attributes: {
udid: 'ios-device-udid',
technology: 'ios',
access_token: 'ios-token-369',
push_id: null,
created_at: '2018-04-25T21:55:56Z',
updated_at: '2018-04-25T21:56:23Z',
app_version: null
}
},
{
id: '371',
type: 'devices',
attributes: {
udid: 'ios-device-udid',
technology: 'ios',
access_token: 'ios-token-371',
push_id: null,
created_at: '2018-04-25T21:57:55Z',
updated_at: '2018-04-25T21:57:56Z',
app_version: null
}
},
{
id: '375',
type: 'devices',
attributes: {
udid: 'ios-device-udid',
technology: 'ios',
access_token: 'ios-token-375',
push_id: null,
created_at: '2018-04-25T22:04:54Z',
updated_at: '2018-04-25T22:04:55Z',
app_version: null
}
},
{
id: '8',
type: 'user_roles',
attributes: {
permanent_link: 'subject',
name: 'Subject',
is_super: false,
is_admin: false,
is_mobile: true,
is_default: false
}
}
]
};
t.context.updateResponseSchedule = {
data: {
id: '5',
type: 'scheduler__personalized_rule_schedules',
attributes: {
start_date: '2017-06-02',
end_date: '2017-09-27',
time: '10:00',
timezone: 'UTC',
relative_schedule: '1,2,4,8,12,14,16',
days_of_week: '0,1,2,3,4,5,6',
relative_unit: null,
start_date_offset: 0,
start_date_offset_unit: null,
skip_exceptions: false,
enabled: false,
exception_days: null,
active_time_start: null,
active_time_end: null
},
relationships: {
mobile_user: {
data: {
id: '74',
type: 'mobile_users'
}
},
scheduleable: {
data: {
id: '4',
type: 'reminder__rules'
}
}
}
}
};
});
test.after('server shut down', () => {});
test.beforeEach((t) => {
client.cache = 'never';
client.authToken = 'valid_token';
mobileUserService.cacheMode = 'networkOnly';
const awardee = new User({ id: 510, email: 'test@test.com' });
awardee.store();
t.context.storage = client.storageUtility;
// t.context.storage.clear();
});
// UserService.addAwardedBadge method
/**
* @test {UserService.addAwardedBadge}
*/
test('[unit] UserService.addAwardedBadge should throw errors for invalid parameters', async (t) => {
const title = 'UserService.addAwardedBadge error';
// undefined mobile user
await t.throwsAsync(mobileUserService.addAwardedBadge(), `${title}: awardedBadge is not defined`);
await t.throwsAsync(mobileUserService.addAwardedBadge({}), `${title}: awardedBadge does not have badge`);
const awardedBadge = new AwardedBadge();
awardedBadge.badge = new Badge();
awardedBadge.awardee = { hello: 'world' };
await t.throwsAsync(mobileUserService.addAwardedBadge(awardedBadge), `${title}: awardee does not have id and badge does not have id`);
awardedBadge.badge.id = 1;
await t.throwsAsync(mobileUserService.addAwardedBadge(awardedBadge), `${title}: awardee does not have id`);
});
/**
* @test {UserService.addAwardedBadge}
*/
test('[unit] UserService.addAwardedBadge should successfully addAwardedBadge (api example)', async (t) => {
// api-doc/1.0/registrations.html
// http://clinical6-docs.s3-website-us-east-1.amazonaws.com/apidoc/v3relationshipsbadges/create.html
const { insertResponseAwardBadge39 } = t.context;
const requestJsonApi = {
data: {
type: 'awarded_badges',
attributes: {},
relationships: {
awardee: {
data: {
type: 'mobile_users',
id: 486
}
},
badge: {
data: {
type: 'badges',
id: 39
}
}
}
}
};
const awardedBadge = new AwardedBadge({});
awardedBadge.awardee = new User({ id: 486 });
awardedBadge.awardee.store();
awardedBadge.badge = new Badge({ id: 39 });
awardedBadge.badge.store();
let request = {};
nock(client.apiBaseUrl).post(`/v3/mobile_users/${awardedBadge.awardee.id}/awarded_badges`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [201, insertResponseAwardBadge39];
});
const response = await mobileUserService.addAwardedBadge(awardedBadge);
t.is(request.path, `/v3/mobile_users/${awardedBadge.awardee.id}/awarded_badges`);
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, 'AwardedBadge');
});
/**
* @test {UserService.update}
*/
test('[unit] UserService.update should enable a user', async (t) => {
const { updateResponseMobileUser9 } = t.context;
let request = {};
nock(client.apiBaseUrl).patch(`/v3/mobile_users/9`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [201, updateResponseMobileUser9];
});
const requestJsonApi = {
data: {
id: 9,
type: 'mobile_users',
attributes: {
account_name: '5nl1xkjc',
username: '5nl1xkjc',
created_at: '2017-05-15T19:08:17.076Z',
email: null,
encryption_key: null,
updated_at: '2017-05-15T19:08:17.108Z',
uuid: 'dddb2ab3-3be9-4a54-8c2c-7687c4ec9bee',
verified_at: null,
invitation_sent_at: null,
invitation_accepted_at: null,
enabled: true
}
}
};
const user = new User(requestJsonApi);
const response = await mobileUserService.update(user);
t.is(request.path, `/v3/mobile_users/9`);
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, 9);
t.is(response.type, 'mobile_users');
t.is(response.disabledAt, null);
});
// UserService.addSchedule method
/**
* @test {UserService.addSchedule}
*/
test('[unit] UserService.addSchedule should throw errors for invalid parameters', async (t) => {
const title = 'UserService.addSchedule error';
// undefined mobile user
await t.throwsAsync(mobileUserService.addSchedule(), `${title}: schedule is not defined`);
await t.throwsAsync(mobileUserService.addSchedule({}), `${title}: user does not have id`);
});
/**
* @test {UserService.addSchedule}
*/
test('[unit] UserService.addSchedule should successfully addSchedule (api example)', async (t) => {
// api-doc/1.0/registrations.html
// http://clinical6-docs.s3-website-us-east-1.amazonaws.com/apidoc/v3relationshipsschedulerpersonalized_rule_schedules/create.html
const requestJsonApi = {
data: {
type: 'scheduler__personalized_rule_schedules',
attributes: {
start_date: '2017-06-02',
relative_schedule: '1,2,4,8,12,14,16',
enabled: true
},
relationships: {
mobile_user: {
data: {
id: 81,
type: 'mobile_users'
}
},
scheduleable: {
data: {
type: 'ediary__entry_groups',
id: 1
}
}
}
}
};
const schedule = new Schedule(requestJsonApi);
schedule.scheduleable = new EntryGroup({ id: 1 });
schedule.scheduleable.store();
schedule.mobileUser = new User({ id: 81 });
schedule.mobileUser.store();
// /v3/mobile_users/${schedule.mobileUser.id}/scheduler/personalized_rule_schedules
let request = {};
nock(client.apiBaseUrl).post(`/v3/mobile_users/${schedule.mobileUser.id}/scheduler/personalized_rule_schedules`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [201, {
data: {
id: '5',
type: 'scheduler__personalized_rule_schedules',
attributes: {
start_date: '2017-06-02',
end_date: null,
time: null,
timezone: null,
relative_schedule: '1,2,4,8,12,14,16',
days_of_week: null,
relative_unit: null,
start_date_offset: null,
start_date_offset_unit: null,
skip_exceptions: null,
enabled: true,
exception_days: null,
active_time_start: null,
active_time_end: null
},
relationships: {
mobile_user: {
data: {
id: 81,
type: 'mobile_users'
}
},
scheduleable: {
data: {
id: '1',
type: 'ediary__entry_groups'
}
}
}
}
}];
});
const response = await mobileUserService.addSchedule(schedule);
t.is(request.path, `/v3/mobile_users/${schedule.mobileUser.id}/scheduler/personalized_rule_schedules`);
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, 'Schedule');
});
// UserService.confirm method
/**
* @test {UserService.confirm}
*/
test('[unit] UserService.confirm should throw errors for invalid parameters', async (t) => {
const undefinedError = 'UserService.confirm error: token is not defined';
const validError = 'UserService.confirm error: token is not a string';
// undefined mobile user
await t.throwsAsync(mobileUserService.confirm(), undefinedError);
await t.throwsAsync(mobileUserService.confirm(1234), validError);
});
// http://clinical6-docs.s3-website-us-east-1.amazonaws.com/apidoc/confirmations/show.html
/**
* @test {UserService.confirm}
*/
test('[unit] UserService.confirm should successfully get the registration status of a mobile user', async (t) => {
const { getResponseConfirmRegistration } = t.context;
let request = {};
nock(client.apiBaseUrl).get(`/v3/mobile_users/confirmation?confirmation_token=ztpt2adhx1l7h3h7e5x1`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, getResponseConfirmRegistration];
});
const response = await mobileUserService.confirm('ztpt2adhx1l7h3h7e5x1');
t.is(request.path, `/v3/mobile_users/confirmation?confirmation_token=ztpt2adhx1l7h3h7e5x1`);
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(response.id, 196);
t.is(response.type, 'mobile_users');
t.is(response.accountName, 'dummy_178');
t.is(response.email, 'user273@fake.com');
t.is(response.createdAt, '2017-06-07T23:58:58Z');
t.is(response.updatedAt, '2017-06-07T23:58:58Z');
t.is(response.disabledAt, '2017-06-07T23:58:58Z');
t.is(response.devices[0].id, 110);
});
/**
* @test {UserService.confirm}
*/
test('[unit] UserService.confirm should throw an error if the token is invalid', async (t) => {
let request = {};
nock(client.apiBaseUrl).get(`/v3/mobile_users/confirmation?confirmation_token=invalid_token`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [422, { confirmation_token: ['is invalid'] }];
});
const response = await mobileUserService.confirm('invalid_token').catch(r => r);
t.is(request.path, `/v3/mobile_users/confirmation?confirmation_token=invalid_token`);
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);
});
// UserService.delete method
/**
* @test {UserService.delete}
*/
test('[unit] UserService.delete should throw errors for invalid parameters', async (t) => {
const undefinedError = 'UserService.delete error: user is not defined';
await t.throwsAsync(mobileUserService.delete(), undefinedError);
});
/**
* @test {UserService.delete}
*/
test('[unit] UserService.delete should receive a valid response for a delete request', async (t) => {
const { deleteRequestMobileUser } = t.context;
const user = new User(deleteRequestMobileUser);
let request = {};
nock(client.apiBaseUrl).delete(`/v3/mobile_users/${user.id}`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [204, { status: 'ok' }];
});
const response = await mobileUserService.delete(user);
t.is(request.path, `/v3/mobile_users/${user.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);
});
/**
* @test {UserService.delete}
*/
test('[unit] UserService.delete should remove the element from local storage', async (t) => {
const { deleteRequestMobileUser, storage } = t.context;
const user = new User(deleteRequestMobileUser);
user.id = 2938;
user.store();
nock(client.apiBaseUrl).delete(`/v3/mobile_users/${user.id}`).reply(204, { status: 'ok' });
await mobileUserService.delete(user);
t.is(storage.has('mobile_users', user.id), false);
});
// UserService.get method
/**
* @test {UserService.get}
*/
test.serial('[unit] UserService.get should throw an error when there is no authToken', async (t) => {
client.authToken = undefined;
const expectedError = 'UserService.get error: requires authToken';
await t.throwsAsync(mobileUserService.get(), expectedError);
});
/**
* @test {UserService.get}
*/
test('[unit] UserService.get should receive a valid response for a get request without an id', async (t) => {
const { getResponse } = t.context;
let request = {};
nock(client.apiBaseUrl).get(`/v3/mobile_users`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, getResponse];
});
const response = await mobileUserService.get();
t.is(request.path, `/v3/mobile_users`);
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, 2);
});
/**
* @test {UserService.get}
*/
test('[unit] UserService.get should receive a valid response for a get request with an id', async (t) => {
const { getResponse2 } = t.context;
let request = {};
nock(client.apiBaseUrl).get(`/v3/mobile_users/2`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, getResponse2];
});
const response = await mobileUserService.get({ id: 2 });
t.is(request.path, `/v3/mobile_users/2`);
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(response.id, 2);
t.is(response.type, 'mobile_users');
t.is(response.uuid, 'dddb2ab3-3be9-4a54-8c2c-7687c4ec9bee');
t.is(response.accountName, '5nl1xkjc');
t.is(response.createdAt, '2017-05-15T19:08:17.076Z');
t.is(response.updatedAt, '2017-05-15T19:08:17.108Z');
});
// UserService.getChildren method
/**
* @test {Clinical6.getChildren}
*/
test.serial('[unit] UserService.getChildren should throw an error when there is no authToken or invalid params', async (t) => {
client.authToken = undefined;
const title = `UserService.getChildren error`;
const user = new User({ id: 22 });
await t.throwsAsync(clinical6.getChildren(user, CohortAssignment), `${title}: requires authToken`);
client.authToken = 'valid_authToken';
await t.throwsAsync(clinical6.getChildren(user), `${title}: child does not have type`);
});
/**
* @test {Clinical6.getChildren}
*/
test.serial(`[unit] UserService.getChildren should receive a valid request and response for a get request for CohortAssignments`, async (t) => {
const { getResponseAssignments80 } = t.context;
const user = new User({ id: 80 });
user.type = 'mobile_users';
user.email = 'myEmail@email.com';
await user.store();
let request = {};
nock(client.apiBaseUrl).get(`/v3/mobile_users/${user.id}/cohort_assignments`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, getResponseAssignments80];
});
const response = await clinical6.getChildren(user, CohortAssignment);
t.is(request.path, `/v3/mobile_users/${user.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, 6);
t.is(response[0].type, 'cohort_assignments');
t.is(response[0].createdAt, '2018-04-25T17:44:57Z');
t.is(response[0].updatedAt, '2018-04-25T17:44:57Z');
t.truthy(response[0].user);
t.is(response[0].user.id, 80);
t.is(response[0].user.email, 'myEmail@email.com');
t.truthy(response[0].cohort);
t.is(response[0].cohort.id, 22);
t.is(response[0].cohort.cohortType, 'static');
t.is(response[0].cohort.createdAt, '2018-04-25T17:44:57Z');
t.is(response[0].cohort.name, 'name-22');
t.is(response[0].cohort.updatedAt, '2018-04-25T17:44:57Z');
t.truthy(response[1] instanceof CohortAssignment);
t.is(response[1].id, 7);
t.is(response[1].type, 'cohort_assignments');
t.is(response[1].createdAt, '2018-04-25T17:44:57Z');
t.is(response[1].updatedAt, '2018-04-25T17:44:57Z');
t.truthy(response[2] instanceof CohortAssignment);
t.is(response[2].id, 8);
t.is(response[2].type, 'cohort_assignments');
t.is(response[2].createdAt, '2018-04-25T17:44:57Z');
t.is(response[2].updatedAt, '2018-04-25T17:44:57Z');
});
/**
* @test {Clinical6.getChildren}
*/
test.serial(`[unit] UserService.getChildren should receive a valid request and response for a get request for AvailableStrategy`, async (t) => {
const { getResponseStrategies77 } = t.context;
const user = new User({ id: 77 });
user.type = 'mobile_users';
user.email = 'myEmail@email.com';
await user.store();
let request = {};
nock(client.apiBaseUrl).get(`/v3/${user.type}/${user.id}/consent/available_strategies`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, getResponseStrategies77];
});
const response = await clinical6.getChildren(user, AvailableStrategy);
t.is(request.path, `/v3/${user.type}/${user.id}/consent/available_strategies`);
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, 2);
t.truthy(response[0] instanceof AvailableStrategy);
t.is(response[0].id, 7);
t.is(response[0].type, 'consent__available_strategies');
t.is(response[0].strategy.id, 7);
t.is(response[0].strategy.type, 'consent__strategies');
t.is(response[0].strategy.name, 'Strategy-8');
t.is(response[0].strategy.cohort.id, 9);
t.is(response[0].strategy.cohort.type, 'cohorts');
t.is(response[0].strategy.forms.length, 2);
t.is(response[0].strategy.forms[0].id, 5);
t.is(response[0].strategy.forms[0].type, 'consent__forms');
t.is(response[0].strategy.forms[1].id, 6);
t.is(response[0].strategy.forms[1].type, 'consent__forms');
t.is(response[0].forms.length, 2);
t.is(response[0].forms[0].id, 5);
t.is(response[0].forms[0].type, 'consent__forms');
t.is(response[0].forms[0].enabled, true);
t.is(response[0].forms[0].name, 'Form 5');
t.is(response[0].forms[0].consentFormVersions.length, 2);
t.is(response[0].forms[0].consentFormVersions[0].id, 5);
t.is(response[0].forms[0].consentFormVersions[0].type, 'consent__form_versions');
t.is(response[0].forms[0].consentFormVersions[1].id, 6);
t.is(response[0].forms[0].consentFormVersions[1].type, 'consent__form_versions');
t.is(response[0].forms[0].consentStrategy.id, 7);
t.is(response[0].forms[0].consentStrategy.type, 'consent__strategies');
t.is(response[0].forms[1].id, 6);
t.is(response[0].forms[1].type, 'consent__forms');
t.is(response[0].forms[1].consentFormVersions.length, 1);
t.is(response[0].forms[1].consentFormVersions[0].id, 7);
t.is(response[0].forms[1].consentFormVersions[0].type, 'consent__form_versions');
t.is(response[0].forms[1].consentStrategy.id, 7);
t.is(response[0].forms[1].consentStrategy.type, 'consent__strategies');
t.truthy(response[1] instanceof AvailableStrategy);
t.is(response[1].id, 8);
t.is(response[1].strategy.id, 8);
t.is(response[1].strategy.type, 'consent__strategies');
t.is(response[1].strategy.name, 'Strategy-9');
t.is(response[1].strategy.cohort.id, 9);
t.is(response[1].strategy.forms.length, 0);
t.is(response[1].forms, undefined);
});
/**
* @test {Clinical6.getChildren}
*/
test.serial(`[unit] UserService.getChildren should receive a valid request and response for a get request for ConsentGrants`, async (t) => {
const { getResponseGrants454 } = t.context;
const user = new User({ id: 80 });
user.type = 'mobile_users';
user.email = 'myEmail@email.com';
await user.store();
let request = {};
nock(client.apiBaseUrl).get(`/v3/mobile_users/${user.id}/consent/grants`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, getResponseGrants454];
});
const response = await clinical6.getChildren(user, ConsentGrant);
t.is(request.path, `/v3/mobile_users/${user.id}/consent/grants`);
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, 2);
t.truthy(response[0] instanceof ConsentGrant);
t.is(response[0].id, 3);
t.is(response[0].type, 'consent__grants');
t.is(response[0].documentUrl, '/uploads/test/consent/grant/document/3/1.pdf');
t.is(response[0].progress, 'all_signed');
t.is(response[0].createdAt, '2018-07-20T13:32:51Z');
t.is(response[0].updatedAt, '2018-07-20T13:32:51Z');
t.truthy(response[0].grantedFor);
t.is(response[0].grantedFor.id, 454);
t.is(response[0].grantedFor.type, 'mobile_users');
t.truthy(response[0].grantedBy);
t.is(response[0].grantedBy.id, 454);
t.is(response[0].grantedBy.type, 'mobile_users');
t.truthy(response[0].strategy);
t.is(response[0].strategy.id, 62);
t.is(response[0].strategy.type, 'consent__strategies');
t.is(response[0].strategy.name, 'Strategy-67');
t.is(response[0].strategy.strategyType, 'paper');
t.is(response[0].strategy.createdAt, '2018-07-20T13:32:51Z');
t.is(response[0].strategy.updatedAt, '2018-07-20T13:32:51Z');
t.is(response[0].strategy.cohort.id, 105);
t.is(response[0].strategy.cohort.type, 'cohorts');
t.is(response[0].strategy.forms.length, 0);
t.is(response[0].formVersion, null);
t.is(response[0].agreement, null);
t.truthy(response[1] instanceof ConsentGrant);
t.is(response[1].id, 4);
t.is(response[1].type, 'consent__grants');
t.is(response[1].signUrl, null);
t.is(response[1].progress, 'all_signed');
t.is(response[1].createdAt, '2018-07-20T13:32:51Z');
t.is(response[1].updatedAt, '2018-07-20T13:32:51Z');
t.truthy(response[1].grantedFor);
t.is(response[1].grantedFor.id, 454);
t.is(response[1].grantedFor.type, 'mobile_users');
t.truthy(response[1].grantedBy);
t.is(response[1].grantedBy.id, 454);
t.is(response[1].grantedBy.type, 'mobile_users');
t.truthy(response[1].strategy);
t.is(response[1].strategy.id, 63);
t.is(response[1].strategy.type, 'consent__strategies');
t.is(response[1].strategy.name, 'Strategy-68');
t.is(response[1].strategy.strategyType, 'electronic');
t.is(response[1].strategy.createdAt, '2018-07-20T13:32:51Z');
t.is(response[1].strategy.updatedAt, '2018-07-20T13:32:51Z');
t.is(response[1].strategy.cohort.id, 106);
t.is(response[1].strategy.cohort.type, 'cohorts');
t.is(response[1].strategy.forms.length, 1);
t.is(response[1].strategy.forms[0].id, 51);
t.is(response[1].strategy.forms[0].type, 'consent__forms');
t.is(response[1].strategy.forms[0].enabled, true);
t.is(response[1].strategy.forms[0].name, 'Form 54');
t.is(response[1].strategy.forms[0].createdAt, '2018-07-20T13:32:51Z');
t.is(response[1].strategy.forms[0].updatedAt, '2018-07-20T13:32:51Z');
t.is(response[1].strategy.forms[0].consentFormVersions.length, 1);
t.is(response[1].strategy.forms[0].consentFormVersions[0].id, 37);
t.is(response[1].strategy.forms[0].consentFormVersions[0].type, 'consent__form_versions');
t.is(response[1].strategy.forms[0].consentStrategy.id, 63);
t.is(response[1].strategy.forms[0].consentStrategy.type, 'consent__strategies');
t.truthy(response[1].formVersion);
t.is(response[1].formVersion.id, 37);
t.is(response[1].formVersion.type, 'consent__form_versions');
t.is(response[1].formVersion.archivedAt, undefined);
t.is(response[1].formVersion.site.id, 115);
t.is(response[1].formVersion.site.type, 'trials__sites');
t.is(response[1].formVersion.agreementTemplate.id, 102);
t.is(response[1].formVersion.agreementTemplate.type, 'agreement__templates');
t.is(response[1].formVersion.language.id, 63);
t.is(response[1].formVersion.language.type, 'languages');
t.is(response[1].formVersion.consentForm.id, 51);
t.is(response[1].formVersion.consentForm.type, 'consent__forms');
t.is(response[1].formVersion.consentForm.type, 'consent__forms');
t.is(response[1].formVersion.consentForm.enabled, true);
t.is(response[1].formVersion.consentForm.name, 'Form 54');
t.is(response[1].formVersion.consentForm.createdAt, '2018-07-20T13:32:51Z');
t.is(response[1].formVersion.consentForm.updatedAt, '2018-07-20T13:32:51Z');
t.is(response[1].formVersion.consentForm.consentFormVersions.length, 1);
t.is(response[1].formVersion.consentForm.consentFormVersions[0].id, 37);
t.is(response[1].formVersion.consentForm.consentFormVersions[0].type, 'consent__form_versions');
t.is(response[1].formVersion.consentForm.consentStrategy.id, 63);
t.is(response[1].formVersion.consentForm.consentStrategy.type, 'consent__strategies');
t.is(response[1].formVersion.approverGroups.length, 0);
t.is(response[1].formVersion.approvers.length, 0);
t.truthy(response[1].agreement);
t.is(response[1].agreement.id, 18);
t.is(response[1].agreement.type, 'agreement__agreements');
});
/**
* @test {Clinical6.getChildren}
*/
test.serial(`[unit] UserService.getChildren should receive a valid request and response for a get request for Video Consultations`, async (t) => {
const { getResponseConsultation } = t.context;
const user = new User({ id: 217 });
user.type = 'mobile_users';
user.email = 'myEmail@email.com';
await user.store();
let request = {};
nock(client.apiBaseUrl).get(`/v3/${user.type}/${user.id}/video_consultations`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, getResponseConsultation];
});
const response = await clinical6.getChildren(user, Consultation);
t.is(request.path, `/v3/mobile_users/${user.id}/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, 3);
t.truthy(response[0] instanceof Consultation);
t.is(response[0].id, 4);
t.is(response[0].type, 'video_consultations');
t.is(response[0].name, 'General Consultation');
t.is(response[0].startAt, '2018-08-09T19:11:32Z');
t.is(response[0].createdAt, '2018-08-09T19:13:05Z');
t.is(response[0].updatedAt, '2018-08-09T19:13:05Z');
t.true(response[0].participants.length > 0);
t.is(response[0].participants[0].id, 2);
t.is(response[0].participants[0].type, 'video_consultation_participants');
t.is(response[0].participants[0].createdAt, '2018-08-09T19:13:05Z');
t.is(response[0].participants[0].updatedAt, '2018-08-09T19:13:05Z');
t.is(response[0].participants[0].user.id, 217);
t.truthy(response[1] instanceof Consultation);
t.is(response[1].id, 5);
t.is(response[1].type, 'video_consultations');
t.is(response[1].name, 'General Consultation');
t.is(response[1].startAt, '2018-08-09T19:11:32Z');
t.is(response[1].createdAt, '2018-08-09T19:13:05Z');
t.is(response[1].updatedAt, '2018-08-09T19:13:05Z');
t.true(response[1].participants.length > 0);
t.is(response[1].participants[0].id, 3);
t.is(response[1].participants[0].type, 'video_consultation_participants');
t.is(response[1].participants[0].createdAt, '2018-08-09T19:13:05Z');
t.is(response[1].participants[0].updatedAt, '2018-08-09T19:13:05Z');
t.is(response[1].participants[0].user.id, 217);
});
// UserService.getAwardedBadges method
/**
* @test {UserService.getAwardedBadges}
*/
test.serial('[unit] UserService.getAwardedBadges should throw an error when there is no authToken', async (t) => {
const expectedError = 'UserService.getAwardedBadges error: requires authToken and awardee does not have id';
client.authToken = undefined;
await t.throwsAsync(mobileUserService.getAwardedBadges(), expectedError);
});
/**
* @test {UserService.getAwardedBadges}
*/
test('[unit] UserService.getAwardedBadges should receive a valid response for a get request without an id', async (t) => {
const awardee = new User({ id: 45 });
let request = {};
nock(client.apiBaseUrl).get(`/v3/mobile_users/${awardee.id}/awarded_badges`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, {
data: [
{
id: '33',
type: 'awarded_badges',
attributes: {
created_at: '2017-08-10T17:54:19Z',
updated_at: '2017-08-10T17:54:19Z',
count: 0,
earned_on_date: null
},
relationships: {
awardee: {
data: {
type: 'mobile_users',
id: '504'
}
},
badge: {
data: {
type: 'badges',
id: '40'
}
}
}
},
{
id: '34',
type: 'awarded_badges',
attributes: {
created_at: '2017-08-10T17:54:19Z',
updated_at: '2017-08-10T17:54:19Z',
count: 0,
earned_on_date: null
},
relationships: {
awardee: {
data: {
type: 'mobile_users',
id: '504'
}
},
badge: {
data: {
type: 'badges',
id: '41'
}
}
}
},
{
id: '35',
type: 'awarded_badges',
attributes: {
created_at: '2017-08-10T17:54:19Z',
updated_at: '2017-08-10T17:54:19Z',
count: 0,
earned_on_date: null
},
relationships: {
awardee: {
data: {
type: 'mobile_users',
id: '504'
}
},
badge: {
data: {
type: 'badges',
id: '42'
}
}
}
}
],
included: [
{
id: '40',
type: 'badges',
attributes: {
created_at: '2017-08-09T16:23:56Z',
updated_at: '2017-08-09T16:23:56Z',
title: 'dummy_462',
description: 'Demo Content info...',
redemption_points: 250,
image: {
image: {
url: '/uploads/test/reward/image/17/1.png',
small: {
url: '/uploads/test/reward/image/17/small_1.png'
},
small_hd: {
url: '/uploads/test/reward/image/17/small_hd_1.png'
},
fullscreen: {
url: '/uploads/test/reward/image/17/fullscreen_1.png'
},
main: {
url: '/uploads/test/reward/image/17/main_1.png'
},
fullscreen_hd: {
url: '/uploads/test/reward/image/17/fullscreen_hd_1.png'
},
main_hd: {
url: '/uploads/test/reward/image/17/main_hd_1.png'
}
}
},
position: 1,
enabled: true,
featured: null,
based_on: null,
threshold: null,
time_unit: null,
start_point: null,
start_at: null,
disabled_image: {
disabled_image: {
url: '/default/default.png',
small: {
url: '/default/small_default.png'
},
small_hd: {
url: '/default/small_hd_default.png'
},
fullscreen: {
url: '/default/fullscreen_default.png'
},
main: {
url: '/default/main_default.png'
},
fullscreen_hd: {
url: '/default/fullscreen_hd_default.png'
},
main_hd: {
url: '/default/main_hd_default.png'
}
}
},
cache_token: 'xMnLvzU_uu4'
}
},
{
id: '41',
type: 'badges',
attributes: {
created_at: '2017-08-09T16:23:56Z',
updated_at: '2017-08-09T16:23:56Z',
title: 'dummy_463',
description: 'Demo Content info...',
redemption_points: 250,
image: {
image: {
url: '/uploads/test/reward/image/18/1.png',
small: {
url: '/uploads/test/reward/image/18/small_1.png'
},
small_hd: {
url: '/uploads/test/reward/image/18/small_hd_1.png'
},
fullscreen: {
url: '/uploads/test/reward/image/18/fullscreen_1.png'
},
main: {
url: '/uploads/test/reward/image/18/main_1.png'
},
fullscreen_hd: {
url: '/uploads/test/reward/image/18/fullscreen_hd_1.png'
},
main_hd: {
url: '/uploads/test/reward/image/18/main_hd_1.png'
}
}
},
position: 2,
enabled: true,
featured: null,
based_on: null,
threshold: null,
time_unit: null,
start_point: null,
start_at: null,
disabled_image: {
disabled_image: {
url: '/default/default.png',
small: {
url: '/default/small_default.png'
},
small_hd: {
url: '/default/small_hd_default.png'
},
fullscreen: {
url: '/default/fullscreen_default.png'
},
main: {
url: '/default/main_default.png'
},
fullscreen_hd: {
url: '/default/fullscreen_hd_default.png'
},
main_hd: {
url: '/default/main_hd_default.png'
}
}
},
cache_token: 'DGMVAICukoc'
}
},
{
id: '42',
type: 'badges',
attributes: {
created_at: '2017-08-09T16:23:56Z',
updated_at: '2017-08-09T16:23:56Z',
title: 'dummy_464',
description: 'Demo Content info...',
redemption_points: 250,
image: {
image: {
url: '/uploads/test/reward/image/19/1.png',
small: {
url: '/uploads/test/reward/image/19/small_1.png'
},
small_hd: {
url: '/uploads/test/reward/image/19/small_hd_1.png'
},
fullscreen: {
url: '/uploads/test/reward/image/19/fullscreen_1.png'
},
main: {
url: '/uploads/test/reward/image/19/main_1.png'
},
fullscreen_hd: {
url: '/uploads/test/reward/image/19/fullscreen_hd_1.png'
},
main_hd: {
url: '/uploads/test/reward/image/19/main_hd_1.png'
}
}
},
position: 3,
enabled: true,
featured: null,
based_on: null,
threshold: null,
time_unit: null,
start_point: null,
start_at: null,
disabled_image: {
disabled_image: {
url: '/default/default.png',
small: {
url: '/default/small_default.png'
},
small_hd: {
url: '/default/small_hd_default.png'
},
fullscreen: {
url: '/default/fullscreen_default.png'
},
main: {
url: '/default/main_default.png'
},
fullscreen_hd: {
url: '/default/fullscreen_hd_default.png'
},
main_hd: {
url: '/default/main_hd_default.png'
}
}
},
cache_token: '6vjdF2bL2Tg'
}
}
]
}];
});
const response = await mobileUserService.getAwardedBadges(awardee);
t.is(request.path, `/v3/mobile_users/${awardee.id}/awarded_badges`);
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);
});
/**
* @test {UserService.getAwardedBadges}
*/
test.serial('[unit] UserService.getAwardedBadges should receive a valid response for a get request with a filter', async (t) => {
const awardee = new User({ id: 510 });
const awardedBadge = { id: 20 };
let request = {};
nock(client.apiBaseUrl).get(`/v3/mobile_users/${awardee.id}/awarded_badges/${awardedBadge.id}`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, {
data: {
id: '20',
type: 'awarded_badges',
attributes: {
created_at: '2017-08-10T17:54:18Z',
updated_at: '2017-08-10T17:54:18Z',
count: 0,
earned_on_date: null
},
relationships: {
awardee: {
data: {
type: 'mobile_users',
id: '510'
}
},
badge: {
data: {
type: 'badges',
id: '41'
}
}
}
},
included: [
{
id: '41',
type: 'badges',
attributes: {
created_at: '2017-08-09T16:23:56Z',
updated_at: '2017-08-09T16:23:56Z',
title: 'dummy_462',
description: 'Demo Content info...',
redemption_points: 250,
image: {
image: {
url: '/uploads/test/reward/image/17/1.png',
small: {
url: '/uploads/test/reward/image/17/small_1.png'
},
small_hd: {
url: '/uploads/test/reward/image/17/small_hd_1.png'
},
fullscreen: {
url: '/uploads/test/reward/image/17/fullscreen_1.png'
},
main: {
url: '/uploads/test/reward/image/17/main_1.png'
},
fullscreen_hd: {
url: '/uploads/test/reward/image/17/fullscreen_hd_1.png'
},
main_hd: {
url: '/uploads/test/reward/image/17/main_hd_1.png'
}
}
},
position: 1,
enabled: true,
featured: null,
based_on: null,
threshold: null,
time_unit: null,
start_point: null,
start_at: null,
disabled_image: {
disabled_image: {
url: '/default/default.png',
small: {
url: '/default/small_default.png'
},
small_hd: {
url: '/default/small_hd_default.png'
},
fullscreen: {
url: '/default/fullscreen_default.png'
},
main: {
url: '/default/main_default.png'
},
fullscreen_hd: {
url: '/default/fullscreen_hd_default.png'
},
main_hd: {
url: '/default/main_hd_default.png'
}
}
},
cache_token: 'xMnLvzU_uu4'
}
}
]
}];
});
const response = await mobileUserService.getAwardedBadges(awardee, awardedBadge);
t.is(request.path, `/v3/mobile_users/${awardee.id}/awarded_badges/${awardedBadge.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.is(response.id, 20);
t.is(response.type, 'awarded_badges');
t.is(response.createdAt, '2017-08-10T17:54:18Z');
t.is(response.updatedAt, '2017-08-10T17:54:18Z');
t.is(response.count, 0);
t.is(response.badge.id, 41);
t.is(response.badge.title, 'dummy_462');
t.is(response.badge.cacheToken, 'xMnLvzU_uu4');
t.is(response.badge.createdAt, '2017-08-09T16:23:56Z');
t.is(response.badge.description, 'Demo Content info...');
t.is(response.badge.enabled, true);
t.is(response.badge.position, 1);
t.is(response.badge.redemptionPoints, 250);
t.is(response.badge.updatedAt, '2017-08-09T16:23:56Z');
t.is(response.awardee.id, 510);
t.is(response.awardee.type, 'mobile_users');
});
// UserService.getEntries method
/**
* @test {UserService.getEntries}
*/
test.serial('[unit] UserService.getEntries should throw an error when there is no authToken', async (t) => {
const expectedError = 'UserService.getEntries error: requires authToken and user is not defined';
client.authToken = undefined;
await t.throwsAsync(mobileUserService.getEntries(), expectedError);
// const noAuthError = 'UserService.getEntries error: requires authToken';
const noIdError = 'UserService.getEntries error: user does not have id';
client.authToken = '1eb4471c95dce68064b8392e02fe8fac';
// await t.throwsAsync(mobileUserService.getEntries({}), noIdError);
await t.throwsAsync(mobileUserService.getEntries({}), noIdError);
});
/**
* @test {UserService.getEntries}
*/
test('[unit] UserService.getEntries should receive a valid response for a get request without an id', async (t) => {
const { getResponseEntries45 } = t.context;
const user = new User({ id: 45 });
let request = {};
nock(client.apiBaseUrl).get(`/v3/mobile_users/${user.id}/ediary/entries`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, getResponseEntries45];
});
const response = await mobileUserService.getEntries(user);
t.is(request.path, `/v3/mobile_users/${user.id}/ediary/entries`);
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(response.length, 2);
});
/**
* @test {UserService.getEntries}
*/
test('[unit] UserService.getEntries should receive a valid response for a get request with a filter', async (t) => {
const user = new User({ id: 49 });
const filters = { entry_group_id: 12, date: '2018-06-02' };
let request = {};
nock(client.apiBaseUrl).get(`/v3/mobile_users/49/ediary/entries?filters[entry_group_id]=12&filters[date]=2018-06-02`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, {
data: [
{
id: '4',
type: 'ediary__entries',
attributes: {
created_at: '2017-06-20T17:55:12Z',
updated_at: '2017-06-20T17:55:12Z',
date: '2018-06-02'
},
relationships: {
entry_group: {
data: {
id: '12',
type: 'ediary__entry_groups'
}
},
flow_process: {
data: {
id: '45',
type: 'data_collection__flow_processes'
}
},
captured_value_group: {
data: null
},
owner: {
data: {
id: '49',
type: 'mobile_users'
}
}
}
}
],
included: [
{
id: '12',
type: 'ediary__entry_groups',
attributes: {
name: 'dummy_396',
permanent_link: 'dummy_397',
position: 4,
category: null,
created_at: '2017-06-20T17:55:12Z',
updated_at: '2017-06-20T17:55:12Z'
},
relationships: {
ediary_entries: {
data: [
{
id: '4',
type: 'ediary__entries'
}
]
},
entry_templates: {
data: []
},
child_entry_groups: {
data: []
},
parent_entry_group: {
data: null
}
}
},
{
id: '45',
type: 'data_collection__flow_processes',
attributes: {
name: 'ipsa',
permanent_link: 'dummy_389',
consent_credentials: null,
created_at: '2017-06-20T17:55:12Z',
updated_at: '2017-06-20T17:55:12Z',
owner_type: 'User',
published_at: null,
conditional_paths: null
},
relationships: {
linked_steps: {
data: []
},
published: {
data: null
},
draft: {
data: null
},
initial_step: {
data: null
}
}
},
{
id: '49',
type: 'mobile_users',
attributes: {
uuid: 'f9996b75-0f0c-4f0a-a2c2-2265b1d2b031',
account_name: 'dummy_49',
email: 'user88@fake.com',
encryption_key: null,
created_at: '2017-06-20T17:55:12Z',
updated_at: '2017-06-20T17:55:12Z',
verified_at: null,
invitation_sent_at: null,
invitation_accepted_at: null
},
relationships: {
devices: {
data: []
}
}
}
]
}];
});
const response = await mobileUserService.getEntries(user, filters);
t.is(request.path, `/v3/mobile_users/${user.id}/ediary/entries?filters[entry_group_id]=12&filters[date]=2018-06-02`);
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(response[0].id, 4);
t.is(response[0].type, 'ediary__entries');
t.is(response[0].createdAt, '2017-06-20T17:55:12Z');
t.is(response[0].date, '2018-06-02');
t.is(response[0].updatedAt, '2017-06-20T17:55:12Z');
t.is(response[0].flow.id, 45);
t.is(response[0].flow.permanentLink, 'dummy_389');
t.is(response[0].flow.name, 'ipsa');
t.is(response[0].flow.steps.length, 0);
t.is(response[0].flow.first_step, null);
t.is(response[0].flow.createdAt, '2017-06-20T17:55:12Z');
t.is(response[0].flow.owner_type, 'User');
});
// UserService.getRegistrationStatus method
/**
* @test {UserService.getRegistrationStatus}
*/
test('[unit] UserService.getRegistrationStatus should throw errors for invalid parameters', async (t) => {
client.authToken = undefined;
const undefinedError = 'UserService.getRegistrationStatus error: attributes is not defined';
const validError = 'UserService.getRegistrationStatus error: attributes must be valid';
// undefined mobile user
await t.throwsAsync(mobileUserService.getRegistrationStatus(), undefinedError);
await t.throwsAsync(mobileUserService.getRegistrationStatus({}), validError);
});
/**
* @test {UserService.getRegistrationStatus}
*/
test('[unit] UserService.getRegistrationStatus should successfully get the registration status of a mobile user', async (t) => {
// api-doc/1.0/registrations.html
// https://sanoficore.clinical6.com/api-doc/1.0/registrations.html
const requestJsonApi = {
data: {
type: 'registration_validations',
attributes: {
account_name: 'account1234'
}
}
};
let request = {};
nock(client.apiBaseUrl).post(`/v3/mobile_users/registration_validation`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, {
data: {
id: '1373',
type: 'statuses',
attributes: {
value: 'new'
},
relationships: {
owner: {
data: {
id: '34',
type: 'mobile_users'
}
},
statusable: {
data: {
id: '34',
type: 'mobile_users'
}
}
}
},
meta: {
password_set: true
}
}];
});
const meta = {};
const response = await mobileUserService.getRegistrationStatus({ account_name: 'account1234' }, meta);
t.is(request.path, `/v3/mobile_users/registration_validation`);
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, undefined);
t.is(response.value, 'new');
t.is(meta.passwordSet, true);
});
// UserService.getSchedules method
/**
* @test {UserService.getSchedules}
*/
test.serial('[unit] UserService.getSchedules should throw an error when there is no authToken', async (t) => {
const expectedError = 'UserService.getSchedules error: requires authToken and user does not have id';
client.authToken = undefined;
await t.throwsAsync(mobileUserService.getSchedules(), expectedError);
});
/**
* @test {UserService.getSchedules}
*/
test('[unit] UserService.getSchedules should receive a valid response for a get request with a filter', async (t) => {
client.authToken = 'valid_token';
const { getResponseSchedules } = t.context;
const user = new User({ id: 72 });
// /v3/mobile_users/${schedule.mobileUser.id}/scheduler/personalized_rule_schedules
let request = {};
nock(client.apiBaseUrl).get(`/v3/mobile_users/${user.id}/scheduler/personalized_rule_schedules`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, getResponseSchedules];
});
const response = await mobileUserService.getSchedules(user);
t.is(request.path, `/v3/mobile_users/${user.id}/scheduler/personalized_rule_schedules`);
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(response.length, 3);
t.is(response[0].constructor.name, 'Schedule');
t.is(response[0].id, 1);
t.is(response[0].daysOfWeek, '0,1,2,3,4,5,6');
t.is(response[0].endDate, '2017-09-27');
t.is(response[0].startDate, '2017-09-10');
t.is(response[0].startDateOffset, 0);
t.is(response[0].time, '10:00');
t.is(response[0].timezone, 'UTC');
t.is(response[0].scheduleable.constructor.name, 'Rule');
t.is(response[0].scheduleable.id, 1);
t.is(response[1].id, 2);
t.is(response[1].daysOfWeek, '0,1,2,3,4,5,6');
t.is(response[1].endDate, '2017-09-27');
t.is(response[1].startDate, '2017-09-10');
t.is(response[1].startDateOffset, 0);
t.is(response[1].time, '10:00');
t.is(response[1].timezone, 'UTC');
t.is(response[1].scheduleable.id, 2);
t.is(response[2].id, 3);
t.is(response[2].daysOfWeek, '0,1,2,3,4,5,6');
t.is(response[2].endDate, '2017-09-27');
t.is(response[2].startDate, '2017-09-10');
t.is(response[2].startDateOffset, 0);
t.is(response[2].time, '10:00');
t.is(response[2].timezone, 'UTC');
t.is(response[2].scheduleable.id, 3);
});
// UserService.getSession method
/**
* @test {UserService.getSession}
*/
test('[unit] UserService.getSession should throw errors for invalid parameters', async (t) => {
const validError = 'UserService.getSession error: token is not a string';
await t.throwsAsync(mobileUserService.getSession(1234), validError);
});
// http://clinical6-docs.s3-website-us-east-1.amazonaws.com/apidoc/sessions/new.html
/**
* @test {UserService.getSession}
*/
test('[unit] UserService.getSession should successfully get the registration status of a mobile user', async (t) => {
let request = {};
nock(client.apiBaseUrl).get(`/v3/mobile_users/sessions?access_token=dd3df48a5c9911838235e9aa4d51346adb5468d7887a25d055f90a5f8448477c`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, {
data: {
id: 493,
type: 'mobile_users',
attributes: {
uuid: '3f6be778-411f-4435-9c7b-d5c4b78c1bff',
account_name: 'dummy_463',
email: null,
created_at: '2018-07-31T18:10:27Z',
updated_at: '2018-07-31T18:10:27Z',
invitation_sent_at: null,
invitation_accepted_at: null,
disabled: false,
disabled_at: null,
password_expired_at: '2018-10-29T18:10:27Z'
},
relationships: {
devices: {
data: [
{
id: 284,
type: 'devices'
}
]
},
user_role: {
data: null
},
profile: {
data: {
id: 867,
type: 'profiles'
}
},
language: {
data: {
id: 1,
type: 'languages'
}
},
patient: {
data: null
},
threads: {
data: []
},
site_member: {
data: null
},
overall_status: {
data: null
}
}
},
included: [
{
id: 284,
type: 'devices',
attributes: {
udid: '269a493krg5kxnfnh04o',
technology: 'ios',
access_token: 'dd3df48a5c9911838235e9aa4d51346adb5468d7887a25d055f90a5f8448477c',
push_id: 'm3cpk0efd6hs2u2mjnnvsqwjhds0hqzxtes6r4h26r7hd1chhjhxa58l28psa34x',
created_at: '2018-07-31T18:10:27Z',
updated_at: '2018-07-31T18:10:27Z',
app_version: null
}
}
]
}];
});
const response = await mobileUserService.getSession('dd3df48a5c9911838235e9aa4d51346adb5468d7887a25d055f90a5f8448477c');
t.is(request.path, `/v3/mobile_users/sessions?access_token=dd3df48a5c9911838235e9aa4d51346adb5468d7887a25d055f90a5f8448477c`);
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(response.id, 493);
t.is(response.uuid, '3f6be778-411f-4435-9c7b-d5c4b78c1bff');
t.is(response.accountName, 'dummy_463');
t.is(response.createdAt, '2018-07-31T18:10:27Z');
t.is(response.updatedAt, '2018-07-31T18:10:27Z');
t.is(response.passwordExpiredAt, '2018-10-29T18:10:27Z');
t.is(response.disabled, false);
t.is(response.disabledAt, null);
t.is(response.devices[0].id, 284);
t.is(response.siteMember, null);
});
// UserService.getSites method
/**
* @test {UserService.getSites}
*/
test.serial('[unit] UserService.getSites should throw errors for invalid token', async (t) => {
client.authToken = undefined;
const validError = 'UserService.getSites error: requires authToken';
await t.throwsAsync(mobileUserService.getSites({ id: 1, type: 'mobile_users' }), validError);
});
/**
* @test {UserService.getSites}
*/
test('[unit] UserService.getSites should throw errors for invalid parameters user type', async (t) => {
const validError = 'UserService.getSites error: user does not have type';
await t.throwsAsync(mobileUserService.getSites({ id: 1 }), validError);
});
/**
* @test {UserService.getSites}
*/
test('[unit] UserService.getSites should throw errors for invalid user id', async (t) => {
const validError = 'UserService.getSites error: user does not have id';
await t.throwsAsync(mobileUserService.getSites({ type: 'mobile_users' }), validError);
});
/**
* @test {UserService.getSites}
*/
test('[unit] UserService.getSites should successfully get the sites and locations of a mobile user', async (t) => {
const user = new User({ id: 1, type: 'mobile_users' });
let request = {};
nock(client.apiBaseUrl).get(`/v3/mobile_users/${user.id}/sites`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, {
data: [
{
id: '8',
type: 'trials__sites',
attributes: {
site_id: '458559',
name: 'Best Site',
email: 'site@site.com',
phone_number: '555-555-5555',
fax_number: null,
contact_name: 'Elwyn Dare',
contact_email: 'leta.hansen@kuphal.info',
contact_phone: null,
contact_fax: null,
created_at: '2018-01-06T02:15:05Z',
updated_at: '2018-01-06T02:15:05Z'
},
relationships: {
location: {
data: {
id: '35',
type: 'locations'
}
},
agreement_templates: {
data: [
{
id: '129',
type: 'agreement__templates'
}
]
}
}
}
],
included: [
{
id: '129',
type: 'agreement__templates',
attributes: {
template_name: 'dummy_818 129',
description: 'Sample agreement template',
expiration: 20,
message: null,
redirect_url: 'http://kriswunsch.io/josie',
approval_required: true,
approver_first_name: 'John',
approver_last_name: 'Doe',
approver_email: 'john@example.com',
created_at: '2017-09-18T18:20:54Z',
updated_at: '2017-09-18T18:20:54Z',
permanent_link: 'dummy81829',
approver_title: 'Mr.',
reminder_frequency: 'WEEKLY_UNTIL_SIGNED'
}
},
{
id: '35',
type: 'locations',
attributes: {
country: 'USA',
state: 'CA',
city: 'San Diego',
street: 'Main',
latitude: '32.8563846',
longitude: '-117.2029363',
title: 'Location Title',
zip_code: null,
address_line_1: 'Main',
address_line_2: null,
address_line_3: null
}
}
]
}];
});
const response = await mobileUserService.getSites(user);
t.is(request.path, `/v3/mobile_users/${user.id}/sites`);
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(response[0].id, 8);
t.is(response[0].siteId, '458559');
t.is(response[0].type, 'trials__sites');
t.is(response[0].name, 'Best Site');
t.is(response[0].location.id, 35);
t.is(response[0].location.country, 'USA');
t.is(response[0].location.state, 'CA');
t.is(response[0].location.city, 'San Diego');
t.is(response[0].location.zipCode, null);
t.is(response[0].agreementTemplates.length, 1);
t.is(response[0].agreementTemplates[0].id, 129);
t.is(response[0].agreementTemplates[0].templateName, 'dummy_818 129');
t.is(response[0].agreementTemplates[0].description, 'Sample agreement template');
t.is(response[0].agreementTemplates[0].documentUrl, undefined);
t.is(response[0].agreementTemplates[0].expiration, 20);
t.is(response[0].agreementTemplates[0].message, null);
t.is(response[0].agreementTemplates[0].redirectUrl, 'http://kriswunsch.io/josie');
t.is(response[0].agreementTemplates[0].createdAt, '2017-09-18T18:20:54Z');
t.is(response[0].agreementTemplates[0].updatedAt, '2017-09-18T18:20:54Z');
t.is(response[0].agreementTemplates[0].permanentLink, 'dummy81829');
t.is(response[0].agreementTemplates[0].reminderFrequency, 'WEEKLY_UNTIL_SIGNED');
t.is(response[0].agreementTemplates[0].archivedAt, undefined);
});
// UserService.insert method
/**
* @test {UserService.insert}
*/
test('[unit] UserService.insert should throw errors for invalid parameters', async (t) => {
const undefinedError = 'UserService.insert error: user is not defined';
await t.throwsAsync(mobileUserService.insert(), undefinedError);
});
/**
* @test {UserService.insert}
*/
test('[unit] UserService.insert should successfully insert mobile user with a mobile user object', async (t) => {
const { insertRequestMobileUser, insertResponseMobileUser } = t.context;
const user = new User(insertRequestMobileUser);
let request = {};
nock(client.apiBaseUrl).post(`/v3/mobile_users`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, insertResponseMobileUser];
});
const response = await mobileUserService.insert(user);
t.is(request.path, `/v3/mobile_users`);
t.is(request.headers.accept, 'application/json');
t.deepEqual(request.requestBody, insertRequestMobileUser);
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, 'mobile_users');
});
// UserService.register method
/**
* @test {UserService.register}
*/
test('[unit] UserService.register should throw errors for invalid parameters', async (t) => {
const undefinedError = 'UserService.register error: attributes is not defined and device is not defined';
const validError = 'UserService.register error: attributes must be valid';
const device = { id: 23 };
await t.throwsAsync(mobileUserService.register(), undefinedError);
await t.throwsAsync(mobileUserService.register({}, device), validError);
await t.throwsAsync(mobileUserService.register({ guest: false }, device), validError);
await t.throwsAsync(mobileUserService.register({ account_name: 'hello@gmail.com' }, device), validError);
await t.throwsAsync(mobileUserService.register({ email: 'hello@gmail.com' }, device), validError);
await t.throwsAsync(mobileUserService.register({ password: '1234' }, device), validError);
});
/**
* @test {UserService.register}
*/
test.serial('[unit] UserService.register should successfully register a guest user to a device (example 1)', async (t) => {
// api-doc/1.0/registrations.html
// https://sanoficore.clinical6.com/api-doc/1.0/registrations.html
const requestJsonApi = {
data: {
type: 'mobile_users',
attributes: {
guest: true
},
relationships: {
devices: {
data: {
id: 76,
type: 'devices'
}
}
}
}
};
let request = {};
nock(client.apiBaseUrl).post(`/v3/mobile_users/registrations`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, {
data: {
id: '136',
type: 'mobile_users',
attributes: {
uuid: '454dbea4-c561-4f6f-8e6e-d095e58a4773',
account_name: 'cthdohmk',
email: null,
encryption_key: null,
created_at: '2017-06-09T23:07:45Z',
updated_at: '2017-06-09T23:07:45Z',
verified_at: null,
invitation_sent_at: null,
invitation_accepted_at: null
},
relationships: {
devices: {
data: [
{
id: '76',
type: 'devices'
}
]
}
}
},
included: [
{
id: '76',
type: 'devices',
attributes: {
udid: '2wxte1bm8fw9nxy7e6fr',
technology: 'ios',
access_token: '81008bfd10f2d623e393352fb0834504',
push_id: 'edh0et0xtllk4a063eb00rmeu82ok82oosjeviyxutzbqal7lq5hmyudf1vbukp7',
created_at: '2017-06-09T23:07:45Z',
updated_at: '2017-06-09T23:07:45Z',
app_version: null
}
}
]
}];
});
const attributes = { guest: true };
const response = await mobileUserService.register(attributes, { id: 76 });
t.is(request.path, `/v3/mobile_users/registrations`);
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, 136);
t.is(response.type, 'mobile_users');
t.is(response.uuid, '454dbea4-c561-4f6f-8e6e-d095e58a4773');
t.is(response.accountName, 'cthdohmk');
t.is(response.createdAt, '2017-06-09T23:07:45Z');
t.is(response.updatedAt, '2017-06-09T23:07:45Z');
const dresp = response.devices[0];
t.is(dresp.id, 76);
t.is(dresp.type, 'devices');
t.is(dresp.udid, '2wxte1bm8fw9nxy7e6fr');
t.is(dresp.technology, 'ios');
t.is(dresp.accessToken, '81008bfd10f2d623e393352fb0834504');
t.is(dresp.pushId, 'edh0et0xtllk4a063eb00rmeu82ok82oosjeviyxutzbqal7lq5hmyudf1vbukp7');
t.is(dresp.createdAt, '2017-06-09T23:07:45Z');
t.is(dresp.updatedAt, '2017-06-09T23:07:45Z');
t.is(client.authToken, 'valid_token');
});
/**
* @test {UserService.register}
*/
test.serial('[unit] UserService.register should successfully register a guest user to a device (example 2)', async (t) => {
let request = {};
nock(client.apiBaseUrl).post(`/v3/mobile_users/registrations`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, {
data: {
id: '4',
type: 'mobile_users',
attributes: {
uuid: '57543ae1-e2dc-40d3-8d6c-01cd74bcc5a8',
account_name: '88e1zppz',
email: null,
encryption_key: null,
created_at: '2017-05-15T19:08:18.110Z',
updated_at: '2017-05-15T19:08:18.122Z',
verified_at: null,
invitation_sent_at: null,
invitation_accepted_at: null
},
relationships: {
devices: {
data: [
{
id: '3',
type: 'devices'
}
]
}
}
},
included: [
{
id: '3',
type: 'devices',
attributes: {
udid: 'mztas1qvch5ic2xg3nx2',
technology: 'ios',
access_token: null,
push_id: 'd6jc3wx3kkigkta4nu5n027m595qh20ctui21bdt0set5znmiliz4qg1bqz9kwp0',
created_at: '2017-05-15T19:08:17.000Z',
updated_at: '2017-05-15T19:08:18.000Z',
app_version: null
}
}
]
}];
});
const requestJsonApi = {
data: {
type: 'mobile_users',
attributes: {
guest: true
},
relationships: {
devices: {
data: {
id: 3,
type: 'devices',
}
}
}
}
};
const attributes = { guest: true };
const response = await mobileUserService.register(attributes, { id: 3 });
t.is(request.path, `/v3/mobile_users/registrations`);
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, 'mobile_users');
t.is(response.uuid, '57543ae1-e2dc-40d3-8d6c-01cd74bcc5a8');
t.is(response.accountName, '88e1zppz');
t.is(response.createdAt, '2017-05-15T19:08:18.110Z');
t.is(response.updatedAt, '2017-05-15T19:08:18.122Z');
const dresp = response.devices[0];
t.is(dresp.id, 3);
t.is(dresp.type, 'devices');
t.is(dresp.udid, 'mztas1qvch5ic2xg3nx2');
t.is(dresp.technology, 'ios');
t.is(dresp.accessToken, null);
t.is(dresp.pushId, 'd6jc3wx3kkigkta4nu5n027m595qh20ctui21bdt0set5znmiliz4qg1bqz9kwp0');
t.is(dresp.createdAt, '2017-05-15T19:08:17.000Z');
t.is(dresp.updatedAt, '2017-05-15T19:08:18.000Z');
t.is(client.authToken, 'valid_token');
});
/**
* @test {UserService.register}
*/
test('[unit] UserService.register should throw an error when registering a guest user to an existing device (example 3)', async (t) => {
let request = {};
nock(client.apiBaseUrl).post(`/v3/mobile_users/registrations`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [422, {
errors: [
{
status: 422,
detail: 'Device already in use.'
}
]
}];
});
const requestJsonApi = {
data: {
type: 'mobile_users',
attributes: {
guest: true
},
relationships: {
devices: {
data: {
id: 5,
type: 'devices',
}
}
}
}
};
const attributes = { guest: true };
let response;
await mobileUserService.register(attributes, { id: 5, type: 'devices' }).catch(res => (response = res));
t.is(request.path, `/v3/mobile_users/registrations`);
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._response.errors.length, 1);
});
/**
* @test {UserService.register}
*/
test.serial('[unit] UserService.register should successfully register a user with account and password to a device (example 4)', async (t) => {
let request = {};
nock(client.apiBaseUrl).post(`/v3/mobile_users/registrations`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, {
data: {
id: '7',
type: 'mobile_users',
attributes: {
uuid: '0b276d4b-25e6-4073-9e66-43489c90b013',
account_name: 'some_identifier',
email: null,
encryption_key: null,
created_at: '2017-05-15T19:08:18.390Z',
updated_at: '2017-05-15T19:08:18.403Z',
verified_at: null,
invitation_sent_at: null,
invitation_accepted_at: null
},
relationships: {
devices: {
data: [
{
id: '6',
type: 'devices'
}
]
}
}
},
included: [
{
id: '6',
type: 'devices',
attributes: {
udid: 'htyatf9r5fkph3wobaf4',
technology: 'ios',
access_token: '12be22de3b09065120193b601ebdbc09',
push_id: 'vyqe0gvfvyhkw8x3ms46qv9ariwdf47pxyp2yg9mkqyhi73mx8ysoii0si6gdmbv',
created_at: '2017-05-15T19:08:18.000Z',
updated_at: '2017-05-15T19:08:18.000Z',
app_version: null
}
}
]
}];
});
const requestJsonApi = {
data: {
type: 'mobile_users',
attributes: {
account_name: 'some_identifier',
password: 'ww3123'
},
relationships: {
devices: {
data: {
id: 6,
type: 'devices',
}
}
}
}
};
const attributes = { account_name: 'some_identifier', password: 'ww3123' };
const response = await mobileUserService.register(attributes, { id: 6, type: 'devices' });
t.is(request.path, `/v3/mobile_users/registrations`);
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, 7);
t.is(response.type, 'mobile_users');
t.is(response.uuid, '0b276d4b-25e6-4073-9e66-43489c90b013');
t.is(response.accountName, 'some_identifier');
t.is(response.createdAt, '2017-05-15T19:08:18.390Z');
t.is(response.updatedAt, '2017-05-15T19:08:18.403Z');
const dresp = response.devices[0];
t.is(dresp.id, 6);
t.is(dresp.type, 'devices');
t.is(dresp.udid, 'htyatf9r5fkph3wobaf4');
t.is(dresp.technology, 'ios');
t.is(dresp.accessToken, '12be22de3b09065120193b601ebdbc09');
t.is(dresp.pushId, 'vyqe0gvfvyhkw8x3ms46qv9ariwdf47pxyp2yg9mkqyhi73mx8ysoii0si6gdmbv');
t.is(dresp.createdAt, '2017-05-15T19:08:18.000Z');
t.is(dresp.updatedAt, '2017-05-15T19:08:18.000Z');
t.is(client.authToken, 'valid_token');
});
// UserService.removeAwardedBadge method
/**
* @test {UserService.removeAwardedBadge}
*/
test('[unit] UserService.removeAwardedBadge should throw errors for invalid parameters', async (t) => {
const title = 'UserService.removeAwardedBadge error';
// undefined mobile user
await t.throwsAsync(mobileUserService.removeAwardedBadge(), `${title}: awardedBadge is not defined`);
await t.throwsAsync(mobileUserService.removeAwardedBadge({}), `${title}: awardedBadge does not have awardee`);
const awardedBadge = new AwardedBadge({ });
awardedBadge.badge = new Badge();
awardedBadge.awardee = { hello: 'world' };
await t.throwsAsync(mobileUserService.removeAwardedBadge(awardedBadge), `${title}: awardee does not have id and awardedBadge does not have id`);
awardedBadge.id = 25;
await t.throwsAsync(mobileUserService.removeAwardedBadge(awardedBadge), `${title}: awardee does not have id`);
awardedBadge.badge.id = 1;
await t.throwsAsync(mobileUserService.removeAwardedBadge(awardedBadge), `${title}: awardee does not have id`);
});
/**
* @test {UserService.removeAwardedBadge}
*/
test('[unit] UserService.removeAwardedBadge should successfully removeAwardedBadge (api example)', async (t) => {
// DELETE //v3/mobile_users/:mobile_user_id/badges/:id
// http://clinical6-docs.s3-website-us-east-1.amazonaws.com/apidoc/v3relationshipsbadges/destroy.html
const { storage } = t.context;
const awardedBadge = new AwardedBadge({ id: 15 });
awardedBadge.awardee = new User({ id: 487 });
awardedBadge.awardee.store();
awardedBadge.badge = new Badge({ id: 62 });
awardedBadge.badge.store();
awardedBadge.store();
t.is(storage.has('awarded_badges', awardedBadge.id), true);
let request = {};
nock(client.apiBaseUrl).delete(`/v3/mobile_users/${awardedBadge.awardee.id}/awarded_badges/${awardedBadge.id}`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [204, { status: 'ok' }];
});
const response = await mobileUserService.removeAwardedBadge(awardedBadge);
t.is(request.path, `/v3/mobile_users/${awardedBadge.awardee.id}/awarded_badges/${awardedBadge.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);
// storage should be empty
t.is(storage.has('awarded_badges', awardedBadge.id), false);
});
// UserService.requestPasswordReset method
/**
* @test {UserService.requestPasswordReset}
*/
test('[unit] UserService.requestPasswordReset should throw errors for invalid parameters', async (t) => {
const undefinedError = 'UserService.requestPasswordReset error: attributes is not defined';
const validError = 'UserService.requestPasswordReset error: attributes must be valid';
await t.throwsAsync(mobileUserService.requestPasswordReset(), undefinedError);
await t.throwsAsync(mobileUserService.requestPasswordReset({}), validError);
});
/**
* @test {UserService.requestPasswordReset}
*/
test('[unit] UserService.requestPasswordReset should successfully requestPasswordReset mobile user with a mobile user object', async (t) => {
const requestJson = {
data: {
type: 'password_resets',
attributes: {
email: 'user116@fake.com'
}
}
};
let request = {};
nock(client.apiBaseUrl).post(`/v3/mobile_users/password`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [201, ''];
});
const response = await mobileUserService.requestPasswordReset({ email: 'user116@fake.com' });
t.is(request.path, `/v3/mobile_users/password`);
t.is(request.headers.accept, 'application/json');
t.deepEqual(request.requestBody, requestJson);
t.is(request.headers['content-type'], 'application/json');
t.is(request.headers.authorization, 'Token token=valid_token');
t.is(response, undefined);
});
/**
* @test {UserService.requestPasswordReset}
*/
test('[unit] UserService.requestPasswordReset should throw an error if the email is invalid', async (t) => {
let request = {};
nock(client.apiBaseUrl).post(`/v3/mobile_users/password`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [422, {
errors: [
{
source: {
pointer: '/data/attributes/email'
},
detail: 'not found'
}
]
}];
});
const requestJsonInvalid = {
data: {
type: 'password_resets',
attributes: {
email: 'invalidEmail@invalid.com'
}
}
};
let response;
await mobileUserService.requestPasswordReset({ email: 'invalidEmail@invalid.com' }).catch(res => (response = res));
t.is(request.path, `/v3/mobile_users/password`);
t.is(request.headers.accept, 'application/json');
t.deepEqual(request.requestBody, requestJsonInvalid);
t.is(request.headers['content-type'], 'application/json');
t.is(request.headers.authorization, 'Token token=valid_token');
t.truthy(response);
});
// UserService.resetPassword method
/**
* @test {UserService.resetPassword}
*/
test('[unit] UserService.resetPassword should throw errors for invalid parameters', async (t) => {
const pre = 'UserService.resetPassword error:';
await t.throwsAsync(mobileUserService.resetPassword(), `${pre} attributes is not defined`);
const attr = {};
const device = new Device({ id: 5 });
await t.throwsAsync(mobileUserService.resetPassword(attr, device), `${pre} attributes does not have reset_password_token and attributes does not have password`);
attr.reset_password_token = 23;
await t.throwsAsync(mobileUserService.resetPassword(attr, device), `${pre} attributes does not have password`);
attr.password = 23;
await t.throwsAsync(mobileUserService.resetPassword(attr, device), `${pre} reset_password_token is not a string and password is not a string`);
attr.reset_password_token = 'asdf';
await t.throwsAsync(mobileUserService.resetPassword(attr, device), `${pre} password is not a string`);
attr.password = 'asdf';
attr.email = 23;
await t.throwsAsync(mobileUserService.resetPassword(attr, device), `${pre} email is not a string and email must be a valid email`);
});
/**
* @test {UserService.resetPassword}
*/
test.serial('[unit] UserService.resetPassword should successfully resetPassword mobile user with correct attributes', async (t) => {
const { updateResponseResetPassword } = t.context;
const requestJson = {
data: {
type: 'password_resets',
attributes: {
reset_password_token: '16700800',
password: 'my_new_sekret',
email: 'test@test.com'
},
relationships: {
devices: {
data: {
id: 375,
type: 'devices'
}
}
}
}
};
let request = {};
nock(client.apiBaseUrl).patch(`/v3/mobile_users/password`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, updateResponseResetPassword];
});
clinical6.device = new Device({
data: {
id: '375',
type: 'devices',
attributes: {
udid: 'ios-device-udid',
technology: 'ios',
access_token: 'ios-token-375-new-device',
push_id: null,
created_at: '2018-04-25T22:04:54Z',
updated_at: '2018-04-25T22:04:54Z',
app_version: null
}
}
});
client.authToken = 'ios-token-375-new-device';
const response = await mobileUserService.resetPassword({
reset_password_token: '16700800',
password: 'my_new_sekret',
email: 'test@test.com'
});
t.is(request.path, `/v3/mobile_users/password`);
t.is(request.headers.accept, 'application/json');
t.deepEqual(request.requestBody, requestJson);
t.is(request.headers['content-type'], 'application/json');
t.is(request.headers.authorization, 'Token token=ios-token-375-new-device');
t.truthy(response);
t.true(response instanceof User);
t.is(response.type, 'mobile_users');
t.is(response.id, 32);
t.is(response.createdAt, '2018-04-16T16:32:36Z');
t.is(response.email, 'myEmail@email.com');
t.is(response.updatedAt, '2018-04-25T22:04:55Z');
t.is(response.uuid, 'my-special-uuid');
t.true(response.role instanceof Role);
t.is(response.role.type, 'user_roles');
t.is(response.role.id, 8);
t.is(response.role.permanentLink, 'subject');
t.is(response.role.name, 'Subject');
t.is(response.role.isSuper, false);
t.is(response.role.isAdmin, false);
t.is(response.role.isMobile, true);
t.is(response.role.isDefault, false);
t.is(client.authToken, 'ios-token-375');
client.reset();
client.authToken = `1eb4471c95dce68064b8392e02fe8fac`;
});
/**
* @test {UserService.resetPassword}
*/
test('[unit] UserService.resetPassword should throw an error if the password token is invalid', async (t) => {
let request = {};
nock(client.apiBaseUrl).patch(`/v3/mobile_users/password`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [422, {
errors: [
{
source: {
pointer: '/data/attributes/reset_password_token'
},
detail: 'is invalid'
}
]
}];
});
const requestJsonInvalid = {
data: {
type: 'password_resets',
attributes: {
reset_password_token: '73169657',
password: 'my_new_sekret',
email: 'test@test.com'
}
}
};
let response;
await mobileUserService.resetPassword({
reset_password_token: '73169657',
password: 'my_new_sekret',
email: 'test@test.com'
}).catch(res => (response = res));
t.is(request.path, `/v3/mobile_users/password`);
t.is(request.headers.accept, 'application/json');
t.deepEqual(request.requestBody, requestJsonInvalid);
t.is(request.headers['content-type'], 'application/json');
t.is(request.headers.authorization, 'Token token=valid_token');
t.truthy(response);
});
// UserService.revokeConsent method
/**
* @test {UserService.revokeConsent}
*/
test('[unit] UserService.revokeConsent should throw errors for invalid parameters', async (t) => {
const undefinedError = 'UserService.revokeConsent error: user is not defined';
const validError = 'UserService.revokeConsent error: user does not have id and user does not have type';
await t.throwsAsync(mobileUserService.revokeConsent(), undefinedError);
await t.throwsAsync(mobileUserService.revokeConsent({}), validError);
});
/**
* @test {UserService.revokeConsent}
*/
test('[unit] UserService.revokeConsent should successfully revoke consent', async (t) => {
// http://clinical6-docs.s3-website-us-east-1.amazonaws.com/apidoc/v3relationshipsconsentconsents/destroy.html
let request = {};
nock(client.apiBaseUrl).delete(`/v3/mobile_users/306/consent/consent`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [204, ''];
});
const response = await mobileUserService.revokeConsent({ id: 306, type: 'mobile_users' });
t.is(request.path, `/v3/mobile_users/306/consent/consent`);
t.is(request.headers.accept, 'application/json');
t.deepEqual(request.requestBody, '');
t.is(request.headers['content-type'], 'application/json');
t.is(request.headers.authorization, 'Token token=valid_token');
t.falsy(response);
});
// UserService.sendConfirmation method
/**
* @test {UserService.sendConfirmation}
*/
test('[unit] UserService.sendConfirmation should throw errors for invalid parameters', async (t) => {
const undefinedError = 'UserService.sendConfirmation error: email is not defined';
const validError = 'UserService.sendConfirmation error: email is not a string';
await t.throwsAsync(mobileUserService.sendConfirmation(), undefinedError);
await t.throwsAsync(mobileUserService.sendConfirmation(1234), validError);
});
/**
* @test {UserService.sendConfirmation}
*/
test('[unit] UserService.sendConfirmation should successfully send a confirmation', async (t) => {
// http://clinical6-docs.s3-website-us-east-1.amazonaws.com/apidoc/confirmations/create.html
const requestJsonApi = {
data: {
type: 'confirmations',
attributes: {
email: 'user277@fake.com'
}
}
};
let request = {};
nock(client.apiBaseUrl).post(`/v3/mobile_users/confirmation`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [201, {}];
});
const response = await mobileUserService.sendConfirmation('user277@fake.com');
t.is(request.path, `/v3/mobile_users/confirmation`);
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);
});
/**
* @test {UserService.sendConfirmation}
*/
test('[unit] UserService.sendConfirmation should throw an error if the email is considered blank', async (t) => {
let request = {};
nock(client.apiBaseUrl).post(`/v3/mobile_users/confirmation`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [422, {
errors: [
{
source: {
pointer: '/data/attributes/email'
},
detail: 'can\'t be blank'
}
]
}];
});
let response;
await mobileUserService.sendConfirmation('user277@fake.com').catch(res => (response = res));
t.is(request.path, `/v3/mobile_users/confirmation`);
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);
});
// UserService.signIn method
/**
* @test {UserService.signIn}
*/
test('[unit] UserService.signIn should throw errors for invalid parameters', async (t) => {
const undefinedError = 'UserService.signIn error: attributes is not defined';
const validError = 'UserService.signIn error: attributes must be valid';
await t.throwsAsync(mobileUserService.signIn(), undefinedError);
await t.throwsAsync(mobileUserService.signIn({}, { id: 5 }), validError);
await t.throwsAsync(mobileUserService.signIn({ account_name: 'hello@gmail.com' }, { id: 5 }), validError);
await t.throwsAsync(mobileUserService.signIn({ email: 'hello@gmail.com' }, { id: 5 }), validError);
await t.throwsAsync(mobileUserService.signIn({ password: '1234' }, { id: 5 }), validError);
});
/**
* @test {UserService.signIn}
*/
test('[unit] UserService.signIn should successfully signIn', async (t) => {
// http://clinical6-docs.s3-website-us-east-1.amazonaws.com/apidoc/confirmations/create.html
const requestJsonApi = {
data: {
type: 'sessions',
attributes: {
account_name: 'dummy_211',
password: 'my_sekret_password'
},
relationships: {
devices: {
data: {
id: 91,
type: 'devices'
}
}
}
}
};
let request = {};
nock(client.apiBaseUrl).post(`/v3/mobile_users/sessions`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [201, {
data: {
id: 154,
type: 'mobile_users',
attributes: {
uuid: 'a519586e-cf05-439f-af8b-c0c1088c8492',
account_name: 'dummy_150',
email: 'user347@fake.com',
created_at: '2018-07-28T02:46:43Z',
updated_at: '2018-07-28T02:46:43Z',
invitation_sent_at: null,
invitation_accepted_at: null,
disabled: false,
disabled_at: null,
password_expired_at: '2018-10-26T02:46:43Z'
},
relationships: {
devices: {
data: [
{
id: 91,
type: 'devices'
}
]
},
user_role: {
data: {
id: 215,
type: 'user_roles'
}
},
profile: {
data: {
id: 343,
type: 'profiles'
}
},
language: {
data: {
id: 1,
type: 'languages'
}
},
patient: {
data: {
id: 6,
type: 'trials__site_members'
}
},
threads: {
data: []
},
site_member: {
data: {
id: 6,
type: 'trials__site_members'
}
},
overall_status: {
data: null
}
}
},
included: [
{
id: 91,
type: 'devices',
attributes: {
udid: 'pvv1tgsczeo5t9i6unfp',
technology: 'ios',
access_token: '591420c626e1dbb019f77c9e2ab426b74d9c0d4a1469ad0a04c5a9801a06ae4d',
push_id: 'csqo7fmp21dhk4ip66ob7kwb18yq3n37jn6jnosvavu9r8dmdns6s001jrb0jly6',
created_at: '2018-07-28T02:46:43Z',
updated_at: '2018-07-28T02:46:43Z',
app_version: null
}
},
{
id: 215,
type: 'user_roles',
attributes: {
permanent_link: 'valid_role',
name: 'aperiam',
is_super: false,
is_admin: false,
is_mobile: false,
is_default: false,
description: 'Random Role normal level'
}
},
{
id: 6,
type: 'trials__site_members',
attributes: {
member_type: 'patient',
consent_status: null,
first_consented_at: null,
last_consented_at: null,
created_at: '2018-07-28T02:46:43Z',
updated_at: '2018-07-28T02:46:43Z'
},
relationships: {
site: {
data: {
id: 47,
type: 'trials__sites'
}
},
mobile_user: {
data: {
id: 154,
type: 'mobile_users'
}
},
consent_strategy: {
data: null
}
}
}
]
}];
});
const response = await mobileUserService.signIn(
{ account_name: 'dummy_211', password: 'my_sekret_password' },
{ id: 91, type: 'device' }
);
t.is(request.path, `/v3/mobile_users/sessions`);
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, undefined);
t.truthy(response.user);
t.is(response.user.id, 154);
t.is(response.user.type, 'mobile_users');
t.is(response.user.uuid, 'a519586e-cf05-439f-af8b-c0c1088c8492');
t.is(response.user.accountName, 'dummy_150');
t.is(response.user.createdAt, '2018-07-28T02:46:43Z');
t.is(response.user.updatedAt, '2018-07-28T02:46:43Z');
t.is(response.user.passwordExpiredAt, '2018-10-26T02:46:43Z');
t.is(response.user.disabled, false);
t.is(response.user.siteMember.id, 6);
t.is(response.user.siteMember.type, 'trials__site_members');
t.is(response.user.siteMember.memberType, 'patient');
t.is(response.user.siteMember.firstConsentedAt, null);
t.is(response.user.siteMember.lastConsentedAt, null);
t.is(response.user.siteMember.consentStatus, null);
t.is(response.user.siteMember.createdAt, '2018-07-28T02:46:43Z');
t.is(response.user.siteMember.updatedAt, '2018-07-28T02:46:43Z');
t.is(response.user.siteMember.site.id, 47);
t.is(response.user.siteMember.site.type, 'trials__sites');
t.is(response.user.siteMember.mobileUser.id, 154);
t.is(response.user.siteMember.mobileUser.type, 'mobile_users');
t.is(response.user.siteMember.consentStrategy, null);
const dresp = response.user.devices[0];
t.is(dresp.id, 91);
t.is(dresp.type, 'devices');
t.is(dresp.udid, 'pvv1tgsczeo5t9i6unfp');
t.is(dresp.technology, 'ios');
t.is(dresp.accessToken, '591420c626e1dbb019f77c9e2ab426b74d9c0d4a1469ad0a04c5a9801a06ae4d');
t.is(dresp.pushId, 'csqo7fmp21dhk4ip66ob7kwb18yq3n37jn6jnosvavu9r8dmdns6s001jrb0jly6');
t.is(dresp.createdAt, '2018-07-28T02:46:43Z');
t.is(dresp.updatedAt, '2018-07-28T02:46:43Z');
t.is(client.authToken, '591420c626e1dbb019f77c9e2ab426b74d9c0d4a1469ad0a04c5a9801a06ae4d');
});
/**
* @test {UserService.signIn}
*/
test('[unit] UserService.signIn should throw an error if the email is considered blank', async (t) => {
let request = {};
nock(client.apiBaseUrl).post(`/v3/mobile_users/sessions`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [422, {
errors: [
{
source: {
pointer: '/data/attributes/email'
},
detail: 'can\'t be blank'
}
]
}];
});
let response;
await mobileUserService.signIn({ email: 'user277@fake.com', password: 'test' }, { id: 134, type: 'device' }).catch(res => (response = res));
t.is(request.path, `/v3/mobile_users/sessions`);
t.is(request.headers.accept, 'application/json');
t.is(request.headers['content-type'], 'application/json');
t.is(request.headers.authorization, undefined);
t.truthy(response);
});
// UserService.unlockUser method
/**
* @test {UserService.unlockUser}
*/
test('[unit] UserService.unlockUser should throw errors for invalid parameters', async (t) => {
const undefinedError = 'UserService.unlockUser error: email is not defined and unlockToken is not defined';
const validError = 'UserService.unlockUser error: unlockToken is not defined and email is not a string';
const validError2 = 'UserService.unlockUser error: email is not a string and unlockToken is not a string';
await t.throwsAsync(mobileUserService.unlockUser(), undefinedError);
await t.throwsAsync(mobileUserService.unlockUser(1234), validError);
await t.throwsAsync(mobileUserService.unlockUser(1234, 1234), validError2);
});
/**
* @test {UserService.unlockUser}
*/
test('[unit] UserService.unlockUser should successfully send a confirmation', async (t) => {
// http://clinical6-docs.s3-website-us-east-1.amazonaws.com/apidoc/v3mobile_usersunlocks/update.html
const requestJsonApi = {
data: {
type: 'mobile_user__unlocks',
attributes: {
email: 'user277@fake.com',
unlock_token: '58031608'
}
}
};
client.authToken = 'valid_token';
let request = {};
nock(client.apiBaseUrl).patch(`/v3/mobile_users/unlock`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, {}];
});
const response = await mobileUserService.unlockUser('user277@fake.com', '58031608');
t.is(request.path, `/v3/mobile_users/unlock`);
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);
});
// UserService.update method
/**
* @test {UserService.update}
*/
test('[unit] UserService.update should successfully update mobile user with a mobile user object', async (t) => {
const { updateResponseMobileUser } = t.context;
const user = new User(updateResponseMobileUser);
let request = {};
nock(client.apiBaseUrl).patch(`/v3/mobile_users/${user.id}`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [201, t.context.updateResponseMobileUser];
});
const response = await mobileUserService.update(user);
t.is(request.path, `/v3/mobile_users/${user.id}`);
t.is(request.headers.accept, 'application/json');
t.deepEqual(request.requestBody, updateResponseMobileUser);
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, 'mobile_users');
});
// UserService.updateAwardedBadge method
/**
* @test {UserService.updateAwardedBadge}
*/
test('[unit] UserService.updateAwardedBadge should throw errors for invalid parameters', async (t) => {
client.authToken = 'valid_token';
const title = 'UserService.updateAwardedBadge error';
// undefined mobile user
await t.throwsAsync(mobileUserService.updateAwardedBadge(), `${title}: awardedBadge is not defined`);
await t.throwsAsync(mobileUserService.updateAwardedBadge({}), `${title}: awardedBadge does not have badge`);
const awardedBadge = new AwardedBadge();
awardedBadge.badge = new Badge();
awardedBadge.awardee = { hello: 'world' };
await t.throwsAsync(mobileUserService.updateAwardedBadge(awardedBadge), `${title}: awardedBadge does not have id and awardee does not have id and badge does not have id`);
awardedBadge.badge.id = 1;
await t.throwsAsync(mobileUserService.updateAwardedBadge(awardedBadge), `${title}: awardedBadge does not have id and awardee does not have id`);
awardedBadge.awardee.id = 1;
await t.throwsAsync(mobileUserService.updateAwardedBadge(awardedBadge), `${title}: awardedBadge does not have id`);
});
/**
* @test {UserService.updateAwardedBadge}
*/
test('[unit] UserService.updateAwardedBadge should successfully updateAwardedBadge (api example)', async (t) => {
// api-doc/1.0/registrations.html
// http://clinical6-docs.s3-website-us-east-1.amazonaws.com/apidoc/v3relationshipsbadges/update.html
const { storage } = t.context;
const requestJsonApi = {
data: {
id: 283,
type: 'awarded_badges',
attributes: {},
relationships: {
awardee: {
data: {
type: 'mobile_users',
id: 583
}
},
badge: {
data: {
type: 'badges',
id: 159
}
}
}
}
};
const awardedBadge = new AwardedBadge({ id: 283 });
awardedBadge.awardee = new User({ id: 583 });
awardedBadge.awardee.store();
awardedBadge.badge = new Badge({ id: 159 });
awardedBadge.badge.store();
let request = {};
nock(client.apiBaseUrl).patch(`/v3/mobile_users/${awardedBadge.awardee.id}/awarded_badges/${awardedBadge.id}`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, {
data: {
id: '20',
type: 'awarded_badges',
attributes: {
created_at: '2017-08-10T17:54:18Z',
updated_at: '2017-08-10T17:54:18Z',
count: 0,
earned_on_date: null
},
relationships: {
awardee: {
data: {
type: 'mobile_users',
id: '510'
}
},
badge: {
data: {
type: 'badges',
id: '41'
}
}
}
},
included: [
{
id: '41',
type: 'badges',
attributes: {
created_at: '2017-08-09T16:23:56Z',
updated_at: '2017-08-09T16:23:56Z',
title: 'dummy_462',
description: 'Demo Content info...',
redemption_points: 250,
image: {
image: {
url: '/uploads/test/reward/image/17/1.png',
small: {
url: '/uploads/test/reward/image/17/small_1.png'
},
small_hd: {
url: '/uploads/test/reward/image/17/small_hd_1.png'
},
fullscreen: {
url: '/uploads/test/reward/image/17/fullscreen_1.png'
},
main: {
url: '/uploads/test/reward/image/17/main_1.png'
},
fullscreen_hd: {
url: '/uploads/test/reward/image/17/fullscreen_hd_1.png'
},
main_hd: {
url: '/uploads/test/reward/image/17/main_hd_1.png'
}
}
},
position: 1,
enabled: true,
featured: null,
based_on: null,
threshold: null,
time_unit: null,
start_point: null,
start_at: null,
disabled_image: {
disabled_image: {
url: '/default/default.png',
small: {
url: '/default/small_default.png'
},
small_hd: {
url: '/default/small_hd_default.png'
},
fullscreen: {
url: '/default/fullscreen_default.png'
},
main: {
url: '/default/main_default.png'
},
fullscreen_hd: {
url: '/default/fullscreen_hd_default.png'
},
main_hd: {
url: '/default/main_hd_default.png'
}
}
},
cache_token: 'xMnLvzU_uu4'
}
}
]
}];
});
const response = await mobileUserService.updateAwardedBadge(awardedBadge);
t.is(request.path, `/v3/mobile_users/${awardedBadge.awardee.id}/awarded_badges/${awardedBadge.id}`);
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, 'AwardedBadge');
storage.clear(awardedBadge.badge.type, awardedBadge.badge.id);
storage.clear(awardedBadge.awardee.type, awardedBadge.awardee.id);
storage.clear(awardedBadge.type, awardedBadge.id);
});
// UserService.updateSchedule method
/**
* @test {UserService.updateSchedule}
*/
test('[unit] UserService.updateSchedule should throw errors for invalid parameters', async (t) => {
const title = 'UserService.updateSchedule error';
// undefined mobile user
await t.throwsAsync(mobileUserService.updateSchedule(), `${title}: schedule is not defined`);
await t.throwsAsync(mobileUserService.updateSchedule({}), `${title}: schedule does not have id`);
const schedule = new Schedule();
await t.throwsAsync(mobileUserService.updateSchedule(schedule), `${title}: schedule does not have id`);
schedule.id = 1;
schedule.mobileUser = new User();
await t.throwsAsync(mobileUserService.updateSchedule(schedule), `${title}: user does not have id`);
});
/**
* @test {UserService.updateSchedule}
*/
test('[unit] UserService.updateSchedule should successfully updateSchedule (api example)', async (t) => {
// api-doc/1.0/registrations.html
// http://clinical6-docs.s3-website-us-east-1.amazonaws.com/apidoc/v3relationshipsschedulerpersonalized_rule_schedules/update.html
const { storage, updateResponseSchedule } = t.context;
const requestJsonApi = {
data: {
id: 5,
type: 'scheduler__personalized_rule_schedules',
attributes: {
start_date: '2017-06-02',
relative_schedule: '1,2,4,8,12,14,16',
enabled: false
},
relationships: {
scheduleable: {
data: {
type: 'reminder__rules',
id: 4
}
},
mobile_user: {
data: {
type: 'mobile_users',
id: 75
}
}
}
}
};
new Rule({ id: 4 }).store();
new User({ id: 75 }).store();
const schedule = new Schedule(requestJsonApi);
await schedule.syncRelationships();
let request = {};
nock(client.apiBaseUrl).patch(`/v3/mobile_users/${schedule.mobileUser.id}/scheduler/personalized_rule_schedules/${schedule.id}`).reply(function (uri, requestBody) {
request = this.req;
request.requestBody = requestBody;
return [200, updateResponseSchedule];
});
const response = await mobileUserService.updateSchedule(schedule);
t.is(request.path, `/v3/mobile_users/${schedule.mobileUser.id}/scheduler/personalized_rule_schedules/${schedule.id}`);
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, 'Schedule');
storage.clear(schedule.mobileUser.type, schedule.mobileUser.id);
storage.clear(schedule.scheduleable.type, schedule.scheduleable.id);
storage.clear(schedule.type, schedule.id);
});