Manual Reference Source Test

test/unit/services.user.v3.invitation-nock.js

import test from 'ava';
import nock from 'nock';
import {
  client,
  mobileUserService,
  userService,
  Device,
  User,
} from '../../src';

test.before('start server', (t) => {
  client.apiBaseUrl = 'https://somesite.Clinical6.com';

  t.context.getInvitationResponse = {
    data: {
      id: 'invitationvalidation',
      type: 'invitation_validations',
      attributes: {
        invitation_token: '59467032',
        email: 'some@thing.com',
        status: 'acceptable'
      }
    }
  };

  t.context.insertMobileUserResponse = {
    data: {
      id: '419',
      type: 'mobile_users',
      attributes: {
        uuid: 'ff030b0a-2f04-4a2f-ab39-59c2c5744b22',
        account_name: '25089567',
        email: 'user631@fake.com',
        created_at: '2018-02-14T16:39:05Z',
        updated_at: '2018-02-14T16:39:05Z',
        verified_at: null,
        invitation_sent_at: '2018-02-14T16:39:05Z',
        invitation_accepted_at: null,
        disabled: false,
        disabled_at: null
      },
      relationships: {
        devices: {
          data: []
        },
        user_role: {
          data: {
            id: '308',
            type: 'user_roles'
          }
        },
        profile: {
          data: {
            id: '650',
            type: 'profiles'
          }
        },
        language: {
          data: {
            id: '1',
            type: 'languages'
          }
        },
        patient: {
          data: null
        }
      }
    }
  };

  t.context.insertUserResponse = {
    data: {
      id: '171',
      type: 'users',
      attributes: {
        uuid: 'b15686e7-8d9c-419e-8fe6-03fa4630fb2c',
        email: 'test@test.com',
        created_at: '2018-02-14T16:38:33Z',
        updated_at: '2018-02-14T16:38:33Z',
        invitation_sent_at: '2018-02-14T16:38:33Z',
        invitation_accepted_at: null,
        disabled_at: null
      },
      relationships: {
        user_role: {
          data: {
            id: '227',
            type: 'user_roles'
          }
        },
        devices: {
          data: []
        },
        profile: {
          data: {
            id: '492',
            type: 'profiles'
          }
        }
      }
    }
  };

  t.context.updateMobileUserResponse = {
    data: {
      id: '10',
      type: 'mobile_users',
      attributes: {
        uuid: 'b5a0d8e9-a988-4a29-aefb-22402f92d58e',
        account_name: 'dummy_7',
        email: 'user10@fake.com',
        encryption_key: 'b00290b6e47e63dc7b221c64c0dc7fec',
        created_at: '2017-08-14T22:55:11Z',
        updated_at: '2017-08-14T22:55:11Z',
        verified_at: null,
        invitation_sent_at: null,
        invitation_accepted_at: '2017-08-14T22:55:11Z'
      },
      relationships: {
        devices: {
          data: [
            {
              id: '4',
              type: 'devices'
            }
          ]
        },
        user_role: {
          data: {
            id: '10',
            type: 'user_roles'
          }
        },
        language: {
          data: {
            id: '4',
            type: 'languages'
          }
        }
      }
    },
    included: [
      {
        id: '4',
        type: 'devices',
        attributes: {
          udid: 'ph2knq8xtg1znvuhrv0h',
          technology: 'ios',
          access_token: '05eaf798ce4bcce9e98ec01843af4881',
          push_id: 'vmp6cl06avq3k2v6ij1z6hv0gaz5y47qx6aotwywq60buoy2sla2hmmulmpbte45',
          created_at: '2017-08-14T22:55:11Z',
          updated_at: '2017-08-14T22:55:11Z',
          app_version: null
        }
      },
      {
        id: '10',
        type: 'user_roles',
        attributes: {
          permanent_link: 'mobile',
          name: 'Default Mobile',
          is_super: false,
          is_admin: false,
          is_mobile: true,
          is_default: true
        }
      }
    ]
  };

  t.context.updateUserResponse = {
    data: {
      id: '110',
      type: 'users',
      attributes: {
        uuid: '09140540-e23f-4ccd-9f99-072fed4f07b3',
        email: 'user326@fake.com',
        created_at: '2018-02-22T19:47:25Z',
        updated_at: '2018-02-22T19:47:25Z',
        invitation_sent_at: '2018-02-22T19:47:25Z',
        invitation_accepted_at: '2018-02-22T19:47:25Z',
        disabled_at: null
      },
      relationships: {
        user_role: {
          data: {
            id: '149',
            type: 'user_roles'
          }
        },
        devices: {
          data: []
        },
        profile: {
          data: {
            id: '337',
            type: 'profiles'
          }
        }
      }
    }
  };
});

test.after('server shut down', () => {});

test.beforeEach((t) => {
  client.cache = 'never';
  client.authToken = 'valid_token';


  t.context.storage = client.storageUtility;
  t.context.mobileUserJsonInvite = {
    data: {
      type: 'invitations',
      attributes: {
        email: 'user633@fake.com'
      },
      relationships: {
        language: {
          data: {
            type: 'languages',
            id: 9
          }
        }
      }
    }
  };
  t.context.mobileUserJsonInviteWithSite = {
    data: {
      type: 'invitations',
      attributes: {
        email: 'user633@fake.com'
      },
      relationships: {
        site: {
          data: {
            type: 'trials__sites',
            id: 15
          }
        }
      }
    }
  };
  t.context.mobileUserJsonInviteWithDP = {
    data: {
      type: 'invitations',
      attributes: {
        email: 'user633@fake.com',
        dynamic_profile: {
          cookies: 52
        }
      }
    }
  };
  t.context.adminUserJsonInvite = {
    data: {
      type: 'invitations',
      attributes: {
        email: 'test@test.com',
        first_name: 'John',
        last_name: 'Doe'
      },
      relationships: {
        user_role: {
          data: {
            type: 'user_roles',
            id: 227
          }
        }
      }
    }
  };
});


// UserService.acceptInvitation method
/**
 * @test {UserService.acceptInvitation}
 */
test('[unit] UserService.acceptInvitation should exist', (t) => {
  t.truthy(mobileUserService.acceptInvitation);
});

/**
 * @test {UserService.acceptInvitation}
 */
test('[unit] UserService.acceptInvitation should throw errors for invalid parameters', async (t) => {
  const title = 'UserService.acceptInvitation error';

  // undefined mobile user
  await t.throwsAsync(mobileUserService.acceptInvitation(), `${title}: token is not defined`);
  await t.throwsAsync(mobileUserService.acceptInvitation({}), `${title}: token is not a string`);

  let token = 'valid_token';
  await t.throwsAsync(mobileUserService.acceptInvitation(token, { device: {} }), `${title}: device does not have id`);
  await t.throwsAsync(mobileUserService.acceptInvitation(token, { email: 'hello' }), `${title}: email is not a valid email`);

  // undefined mobile user
  token = undefined;
  await t.throwsAsync(userService.acceptInvitation(), `${title}: token is not defined`);
  await t.throwsAsync(userService.acceptInvitation({}), `${title}: token is not a string`);

  token = 'valid_token';
  await t.throwsAsync(userService.acceptInvitation(token, { device: {} }), `${title}: device does not have id`);
  await t.throwsAsync(userService.acceptInvitation(token, { email: 'hello' }), `${title}: email is not a valid email`);
});

/**
 * @test {UserService.acceptInvitation}
 */
test('[unit] UserService.acceptInvitation should successfully accept an invitation for a mobile user', async (t) => {
  const { updateMobileUserResponse } = t.context;

  let request = {};
  nock(client.apiBaseUrl).patch(`/v3/mobile_users/invitation`).reply(function (uri, requestBody) {
    request = this.req;
    request.requestBody = requestBody;
    return [200, updateMobileUserResponse];
  });

  const requestJsonApi = {
    data: {
      type: 'invitations',
      attributes: {
        invitation_token: '15886891',
        password: `123456`
      },
      relationships: {
        devices: {
          data: {
            type: 'devices',
            id: 4
          }
        }
      }
    }
  };

  const device = new Device({ id: 4 });
  device.store();
  const response = await mobileUserService.acceptInvitation('15886891', { password: '123456', device });

  t.is(request.path, `/v3/mobile_users/invitation`);
  t.is(request.headers.accept, 'application/json');
  t.deepEqual(request.requestBody, requestJsonApi);
  t.is(request.headers['content-type'], 'application/json');
  t.is(request.headers.authorization, 'Token token=valid_token');
  t.truthy(response);
  t.is(response.constructor.name, 'User');
});

/**
 * @test {UserService.acceptInvitation}
 */
test('[unit] UserService.acceptInvitation should successfully accept an invitation for a user', async (t) => {
  const { updateUserResponse } = t.context;

  let request = {};
  nock(client.apiBaseUrl).patch(`/v3/users/invitation`).reply(function (uri, requestBody) {
    request = this.req;
    request.requestBody = requestBody;
    return [200, updateUserResponse];
  });

  const requestJsonApi = {
    data: {
      type: 'invitations',
      attributes: {
        invitation_token: '15886891',
        password: `123456`
      },
      relationships: {
        devices: {
          data: {
            type: 'devices',
            id: 4
          }
        }
      }
    }
  };

  const device = new Device({ id: 4 });
  device.store();
  const response = await userService.acceptInvitation('15886891', { password: '123456', device });

  t.is(request.path, `/v3/users/invitation`);
  t.is(request.headers.accept, 'application/json');
  t.deepEqual(request.requestBody, requestJsonApi);
  t.is(request.headers['content-type'], 'application/json');
  t.is(request.headers.authorization, 'Token token=valid_token');
  t.truthy(response);
  t.is(response.constructor.name, 'User');
});


// UserService.getInvitationStatus method
/**
 * @test {UserService.getInvitationStatus}
 */
test.serial('[unit] UserService.getInvitationStatus should throw an error when there is no authToken', async (t) => {
  client.authToken = undefined;
  const title = `UserService.getInvitationStatus error`;
  await t.throwsAsync(userService.getInvitationStatus(), `${title}: requires authToken and invitation_token is not defined`);
  await t.throwsAsync(userService.getInvitationStatus(undefined, { invitation_token: 'asdf' }), `${title}: requires authToken`);
});

/**
 * @test {UserService.getInvitationStatus}
 */
test('[unit] UserService.getInvitationStatus should successfully get the invitaiton status', async (t) => {
  const { getInvitationResponse } = t.context;
  let request = {};
  nock(client.apiBaseUrl).post(`/v3/mobile_users/invitation/status`).reply(function (uri, requestBody) {
    request = this.req;
    request.requestBody = requestBody;
    return [201, getInvitationResponse];
  });

  const requestJsonApi = {
    data: {
      type: 'invitations',
      attributes: {
        invitation_token: '59467032',
        email: 'some@thing.com'
      }
    }
  };

  const user = new User({ email: 'some@thing.com' });
  user.type = 'mobile_users';
  const response = await mobileUserService.getInvitationStatus(user, { invitation_token: '59467032' });

  t.is(request.path, `/v3/mobile_users/invitation/status`);
  t.is(request.headers.accept, 'application/json');
  t.deepEqual(request.requestBody, requestJsonApi);
  t.is(request.headers['content-type'], 'application/json');
  t.is(request.headers.authorization, 'Token token=valid_token');
  t.is(response.id, 'invitationvalidation');
  t.is(response.type, 'invitation_validations');
  t.is(response.invitationToken, '59467032');
  t.is(response.email, 'some@thing.com');
});


// // SiteService.update method
// /**
//  * @test {Clinical6.update}
//  */
// test.serial('[unit] SiteService.update should throw an error when there is no authToken', async (t) => {
//   client.authToken = undefined;
//   const title = `SiteService.update error`;
//   await t.throwsAsync(clinical6.update(new Site({ id: 5 })), `${title}: requires authToken`);
// });

// /**
//  * @test {Clinical6.update}
//  */
// test('[unit] SiteService.update should successfully update a site with a site object', async (t) => {
//   const { site, updateResponse, siteJsonApi } = t.context;
//   new Location({ id: 117 }).store();

//   let request = {};
//   nock(client.apiBaseUrl).patch(`/v3/mobile_users/invitation/status/${site.id}`).reply(function (uri, requestBody) {
//     request = this.req;
//     request.requestBody = requestBody;
//     return [200, updateResponse];
//   });

//   const response = await clinical6.update(site);

//   t.is(request.path, `/v3/mobile_users/invitation/status/${site.id}`);
//   t.is(request.headers.accept, 'application/json');
//   t.deepEqual(request.requestBody, siteJsonApi);
//   t.is(request.headers['content-type'], 'application/json');
//   t.is(request.headers.authorization, 'Token token=valid_token');
//   t.is(response.id, 18);
//   t.is(response.type, 'trials__sites');
// });