Manual Reference Source Test

test/unit/services.cohort.js

import test from 'ava';
import nock from 'nock';
import {
  client,
  clinical6,
  Cohort,
  CohortAssignment,
} from '../../src';

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

  t.context.getResponseAll = {
    data: [
      {
        id: '17',
        type: 'cohorts',
        attributes: {
          name: 'name-17',
          cohort_type: 'static',
          created_at: '2018-04-17T16:14:07Z',
          updated_at: '2018-04-17T16:14:07Z'
        }
      },
      {
        id: '18',
        type: 'cohorts',
        attributes: {
          name: 'name-18',
          cohort_type: 'static',
          created_at: '2018-04-17T16:14:07Z',
          updated_at: '2018-04-17T16:14:07Z'
        }
      },
      {
        id: '19',
        type: 'cohorts',
        attributes: {
          name: 'name-19',
          cohort_type: 'static',
          created_at: '2018-04-17T16:14:07Z',
          updated_at: '2018-04-17T16:14:07Z'
        }
      },
      {
        id: '20',
        type: 'cohorts',
        attributes: {
          name: 'name-20',
          cohort_type: 'dynamic',
          created_at: '2018-04-17T16:14:07Z',
          updated_at: '2018-04-17T16:14:07Z'
        },
        relationships: {
          filter_group: {
            data: {
              id: '3',
              type: 'filter_groups'
            }
          }
        }
      },
      {
        id: '21',
        type: 'cohorts',
        attributes: {
          name: 'name-21',
          cohort_type: 'dynamic',
          created_at: '2018-04-17T16:14:07Z',
          updated_at: '2018-04-17T16:14:07Z'
        },
        relationships: {
          filter_group: {
            data: {
              id: '4',
              type: 'filter_groups'
            }
          }
        }
      }
    ],
    included: [
      {
        id: '3',
        type: 'filter_groups',
        attributes: {
          operator: 'and',
          created_at: '2018-04-17T16:14:07Z',
          updated_at: '2018-04-17T16:14:07Z'
        },
        relationships: {
          cohort: {
            data: {
              id: '20',
              type: 'cohorts'
            }
          }
        }
      },
      {
        id: '4',
        type: 'filter_groups',
        attributes: {
          operator: 'and',
          created_at: '2018-04-17T16:14:07Z',
          updated_at: '2018-04-17T16:14:07Z'
        },
        relationships: {
          cohort: {
            data: {
              id: '21',
              type: 'cohorts'
            }
          }
        }
      }
    ]
  };

  t.context.getResponseId = {
    data: {
      id: '23',
      type: 'cohorts',
      attributes: {
        name: 'name-25',
        cohort_type: 'dynamic',
        created_at: '2018-04-17T16:14:08Z',
        updated_at: '2018-04-17T16:14:08Z'
      },
      relationships: {
        filter_group: {
          data: {
            id: '5',
            type: 'filter_groups'
          }
        }
      }
    },
    included: [
      {
        id: '5',
        type: 'filter_groups',
        attributes: {
          operator: 'and',
          created_at: '2018-04-17T16:14:08Z',
          updated_at: '2018-04-17T16:14:08Z'
        },
        relationships: {
          cohort: {
            data: {
              id: '23',
              type: 'cohorts'
            }
          }
        }
      }
    ]
  };

  t.context.getResponseAssignments = {
    data: [
      {
        id: '4',
        type: 'cohort_assignments',
        attributes: {
          created_at: '2018-04-17T19:59:54Z',
          updated_at: '2018-04-17T19:59:54Z'
        },
        relationships: {
          user: {
            data: {
              id: '152',
              type: 'users'
            }
          },
          cohort: {
            data: {
              id: '9',
              type: 'cohorts'
            }
          }
        }
      },
      {
        id: '5',
        type: 'cohort_assignments',
        attributes: {
          created_at: '2018-04-17T19:59:54Z',
          updated_at: '2018-04-17T19:59:54Z'
        },
        relationships: {
          user: {
            data: {
              id: '153',
              type: 'users'
            }
          },
          cohort: {
            data: {
              id: '9',
              type: 'cohorts'
            }
          }
        }
      },
      {
        id: '6',
        type: 'cohort_assignments',
        attributes: {
          created_at: '2018-04-17T19:59:54Z',
          updated_at: '2018-04-17T19:59:54Z'
        },
        relationships: {
          user: {
            data: {
              id: '154',
              type: 'users'
            }
          },
          cohort: {
            data: {
              id: '9',
              type: 'cohorts'
            }
          }
        }
      }
    ],
    included: [
      {
        id: '152',
        type: 'users',
        attributes: {
          uuid: '7731e5db-3c94-4596-8a52-cb753b9d23bd',
          email: 'user418@fake.com',
          created_at: '2018-04-17T19:59:54Z',
          updated_at: '2018-04-17T19:59:54Z',
          invitation_sent_at: null,
          invitation_accepted_at: null,
          disabled_at: null
        },
        relationships: {
          user_role: {
            data: {
              id: '192',
              type: 'user_roles'
            }
          },
          devices: {
            data: []
          },
          profile: {
            data: {
              id: '431',
              type: 'profiles'
            }
          }
        }
      },
      {
        id: '153',
        type: 'users',
        attributes: {
          uuid: '6d97ee61-543f-4778-adea-c2a3537d4532',
          email: 'user419@fake.com',
          created_at: '2018-04-17T19:59:54Z',
          updated_at: '2018-04-17T19:59:54Z',
          invitation_sent_at: null,
          invitation_accepted_at: null,
          disabled_at: null
        },
        relationships: {
          user_role: {
            data: {
              id: '192',
              type: 'user_roles'
            }
          },
          devices: {
            data: []
          },
          profile: {
            data: {
              id: '432',
              type: 'profiles'
            }
          }
        }
      },
      {
        id: '154',
        type: 'users',
        attributes: {
          uuid: '3536a5bb-0404-4202-a15e-e13b0d705c36',
          email: 'user420@fake.com',
          created_at: '2018-04-17T19:59:54Z',
          updated_at: '2018-04-17T19:59:54Z',
          invitation_sent_at: null,
          invitation_accepted_at: null,
          disabled_at: null
        },
        relationships: {
          user_role: {
            data: {
              id: '192',
              type: 'user_roles'
            }
          },
          devices: {
            data: []
          },
          profile: {
            data: {
              id: '433',
              type: 'profiles'
            }
          }
        }
      }
    ]
  };

  t.context.getResponseAssignment20 = {
    data: {
      id: '20',
      type: 'cohort_assignments',
      attributes: {
        created_at: '2018-04-17T19:59:53Z',
        updated_at: '2018-04-17T19:59:53Z'
      },
      relationships: {
        user: {
          data: {
            id: '278',
            type: 'mobile_users'
          }
        },
        cohort: {
          data: {
            id: '2',
            type: 'cohorts'
          }
        }
      }
    },
    included: [
      {
        id: '278',
        type: 'mobile_users',
        attributes: {
          uuid: '7731e5db-3c94-4596-8a52-cb753b9d23bd',
          email: 'user418@fake.com',
          created_at: '2018-04-17T19:59:54Z',
          updated_at: '2018-04-17T19:59:54Z',
          invitation_sent_at: null,
          invitation_accepted_at: null,
          disabled_at: null
        },
        relationships: {
          user_role: {
            data: {
              id: '192',
              type: 'user_roles'
            }
          },
          devices: {
            data: []
          },
          profile: {
            data: {
              id: '431',
              type: 'profiles'
            }
          }
        }
      }
    ]
  };

  t.context.patchResponse = {
    data: {
      id: '25',
      type: 'cohorts',
      attributes: {
        name: 'new-name',
        cohort_type: 'dynamic',
        created_at: '2018-04-17T16:14:08Z',
        updated_at: '2018-04-17T16:14:08Z'
      },
      relationships: {
        filter_group: {
          data: null
        }
      }
    }
  };

  t.context.postResponse = {
    data: {
      id: 1,
      type: 'cohorts',
      attributes: {
        name: 'name',
        cohort_type: 'static',
        created_at: '2018-04-03T14:16:25Z',
        updated_at: '2018-04-03T14:16:25Z'
      }
    }
  };

  t.context.cohortJsonApi = {
    data: {
      id: 25,
      type: 'cohorts',
      attributes: {
        name: 'name',
        cohort_type: 'static'
      }
    }
  };
});

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

test.beforeEach((t) => {
  client.cache = 'never';
  client.authToken = 'valid_token';
  t.context.cohort = new Cohort(t.context.cohortJsonApi);
});


// CohortService.delete method
/**
 * @test {Clinical6.delete}
 */
test('[unit] CohortService.delete should throw errors for invalid parameters', async (t) => {
  const title = `CohortService.delete error`;
  await t.throwsAsync(clinical6.delete(new Cohort()), `${title}: cohort does not have id`);
});

/**
 * @test {Clinical6.delete}
 */
test('[unit] CohortService.delete should receive a valid response for a delete request', async (t) => {
  const { cohort } = t.context;
  cohort.id = 5;
  let request = {};
  nock(client.apiBaseUrl).delete(`/v3/cohorts/${cohort.id}`).reply(function (uri, requestBody) {
    request = this.req;
    request.requestBody = requestBody;
    return [200, ''];
  });
  const response = await clinical6.delete(cohort);
  t.is(request.path, `/v3/cohorts/${cohort.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.falsy(response);
});

/**
 * @test {Clinical6.delete}
 */
test.serial('[unit] CohortService.delete should remove the element from local storage', async (t) => {
  const { cohort, storage } = t.context;
  cohort.id = 5;
  nock(client.apiBaseUrl).delete(`/v3/cohorts/${cohort.id}`).reply(200, '');
  await storage.set(cohort.type, cohort.toJSON(), { id: cohort.id });
  await clinical6.delete(cohort);
  t.is(storage.has(cohort.type, { id: cohort.id }), false);
});


// CohortService.get method
/**
 * @test {Clinical6.get}
 */
test.serial('[unit] CohortService.get should throw an error when there is no authToken', async (t) => {
  client.authToken = undefined;
  const expectedError = 'CohortService.get error: requires authToken';
  await t.throwsAsync(clinical6.get(Cohort), expectedError);
});

/**
 * @test {Clinical6.get}
 */
test('[unit] CohortService.get should make a properly formatted get request and response without an id', async (t) => {
  const { getResponseAll } = t.context;
  let request = {};
  nock(client.apiBaseUrl).get('/v3/cohorts').reply(function () {
    request = this.req;
    return [200, getResponseAll];
  });
  const response = await clinical6.get(Cohort);
  t.is(request.path, `/v3/cohorts`);
  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, 5);
});

/**
 * @test {Clinical6.get}
 */
test('[unit] CohortService.get should receive a valid response for a get request with an id', async (t) => {
  const { getResponseId } = t.context;
  nock(client.apiBaseUrl).get('/v3/cohorts/4').reply(200, getResponseId);
  const response = await clinical6.get(new Cohort({ id: 4 }));
  t.truthy(response);
  t.is(response.id, 23);
  t.is(response.type, 'cohorts');
  t.is(response.createdAt, '2018-04-17T16:14:08Z');
  t.is(response.updatedAt, '2018-04-17T16:14:08Z');
  t.is(response.name, 'name-25');
  t.is(response.cohortType, 'dynamic');
});


// CohortService.getChildren method
/**
 * @test {Clinical6.getChildren}
 */
test.serial('[unit] CohortService.getChildren should throw an error when there is no authToken or invalid params', async (t) => {
  client.authToken = undefined;
  const title = `CohortService.getChildren error`;
  const cohort = new Cohort({ id: 22 });

  await t.throwsAsync(clinical6.getChildren(cohort, CohortAssignment), `${title}: requires authToken`);
  client.authToken = 'valid_authToken';
  await t.throwsAsync(clinical6.getChildren(cohort), `${title}: child does not have type`);
});

/**
 * @test {Clinical6.getChildren}
 */
test(`[unit] CohortService.getChildren should receive a valid request and response for a get request without an id`, async (t) => {
  const { getResponseAssignments } = t.context;
  const cohort = new Cohort({ id: 22 });

  let request = {};
  nock(client.apiBaseUrl).get(`/v3/cohorts/${cohort.id}/cohort_assignments`).reply(function (uri, requestBody) {
    request = this.req;
    request.requestBody = requestBody;
    return [200, getResponseAssignments];
  });

  const response = await clinical6.getChildren(cohort, CohortAssignment);
  t.is(request.path, `/v3/cohorts/${cohort.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, 4);
  t.is(response[0].type, 'cohort_assignments');
  t.is(response[0].createdAt, '2018-04-17T19:59:54Z');
  t.is(response[0].updatedAt, '2018-04-17T19:59:54Z');
  t.truthy(response[0].user);
  t.is(response[0].user.id, 152);
  t.is(response[0].user.createdAt, '2018-04-17T19:59:54Z');
  t.is(response[0].user.email, 'user418@fake.com');
  t.is(response[0].user.updatedAt, '2018-04-17T19:59:54Z');
  t.is(response[0].user.uuid, '7731e5db-3c94-4596-8a52-cb753b9d23bd');
  t.truthy(response[1] instanceof CohortAssignment);
  t.is(response[1].id, 5);
  t.is(response[1].type, 'cohort_assignments');
  t.is(response[1].createdAt, '2018-04-17T19:59:54Z');
  t.is(response[1].updatedAt, '2018-04-17T19:59:54Z');
  t.truthy(response[2] instanceof CohortAssignment);
  t.is(response[2].id, 6);
  t.is(response[2].type, 'cohort_assignments');
  t.is(response[2].createdAt, '2018-04-17T19:59:54Z');
  t.is(response[2].updatedAt, '2018-04-17T19:59:54Z');
});

/**
 * @test {Clinical6.getChildren}
 */
test('[unit] CohortService.getChildren should receive a valid response for a get request with an id', async (t) => {
  const { getResponseAssignment20 } = t.context;
  const cohort = new Cohort({ id: 22 });
  const cohortAssignment = new CohortAssignment({ id: 20 });

  let request = {};
  nock(client.apiBaseUrl).get(`/v3/cohorts/${cohort.id}/cohort_assignments/${cohortAssignment.id}`).reply(function (uri, requestBody) {
    request = this.req;
    request.requestBody = requestBody;
    return [200, getResponseAssignment20];
  });

  const response = await clinical6.getChildren(cohort, { id: 20, type: CohortAssignment.type });
  t.is(request.path, `/v3/cohorts/${cohort.id}/cohort_assignments/${cohortAssignment.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.truthy(response instanceof CohortAssignment);
  t.is(response.id, 20);
  t.is(response.type, 'cohort_assignments');
  t.is(response.createdAt, '2018-04-17T19:59:53Z');
  t.is(response.updatedAt, '2018-04-17T19:59:53Z');
  t.truthy(response.user);
  t.is(response.user.id, 278);
  t.is(response.user.createdAt, '2018-04-17T19:59:54Z');
  t.is(response.user.email, 'user418@fake.com');
  t.is(response.user.updatedAt, '2018-04-17T19:59:54Z');
  t.is(response.user.uuid, '7731e5db-3c94-4596-8a52-cb753b9d23bd');
  t.truthy(response.cohort);
  t.is(response.cohort.id, 2);
  t.is(response.cohort.type, 'cohorts');
});


// CohortService.insert method
/**
 * @test {Clinical6.insert}
 */
test.serial('[unit] CohortService.insert should throw an error when there is no authToken', async (t) => {
  client.authToken = undefined;
  const expectedError = 'CohortService.insert error: requires authToken';
  await t.throwsAsync(clinical6.insert(new Cohort()), expectedError);
});

/**
 * @test {Clinical6.insert}
 */
test('[unit] CohortService.insert should successfully insert a cohort with a cohort object', async (t) => {
  const { postResponse } = t.context;
  let request = {};
  nock(client.apiBaseUrl).post(`/v3/cohorts`).reply(function (uri, requestBody) {
    request = this.req;
    request.requestBody = requestBody;
    return [200, postResponse];
  });

  const requestJsonApi = {
    data: {
      type: 'cohorts',
      attributes: {
        name: 'name',
        cohort_type: 'static'
      }
    }
  };

  const cohort = new Cohort(requestJsonApi);
  const response = await clinical6.insert(cohort);

  t.is(request.path, `/v3/cohorts`);
  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, 1);
  t.is(response.type, 'cohorts');
  t.is(response.name, 'name');
  t.is(response.cohortType, 'static');
  t.is(response.createdAt, '2018-04-03T14:16:25Z');
  t.is(response.updatedAt, '2018-04-03T14:16:25Z');
});

// CohortService.update method
/**
 * @test {Clinical6.update}
 */
test('[unit] CohortService.update should successfully update a cohort with a cohort object', async (t) => {
  const { cohort, patchResponse, cohortJsonApi } = t.context;
  let request = {};
  nock(client.apiBaseUrl).patch(/\/v3\/cohorts\/([0-9]*)$/).reply(function (uri, requestBody) {
    request = this.req;
    request.requestBody = requestBody;
    return [200, patchResponse];
  });
  const response = await clinical6.update(cohort);

  t.is(request.path, `/v3/cohorts/${cohort.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.deepEqual(request.requestBody, cohortJsonApi);
  t.is(response.id, 25);
  t.is(response.type, 'cohorts');
});