/* tslint:disable: no-unused-expression */ import nock from 'nock' import chai, { expect } from 'chai' import chaiAsPromised from 'chai-as-promised' import aitmedApi from '../client' import * as E from '../customErrors' import * as types from '../types/sdk' chai.use(chaiAsPromised) const tvKeys = { accountId: 'some_accountId', groupIds: 'some_groupIds', passwordResetFlowId: 'some_passwordResetFlowId', registerToken: 'some_registerToken', scopedAccessToken: 'some_scopedAccessToken', vaultId: 'some_vaultId', appointmentVaultId: 'some_appointmentVaultId', sentryApiKey: 'some_sentryApiKey', googleApiKey: 'some_googleApiKey', } const baseURL = 'https://testapi.aitmed.com' const baseTvURL = 'https://api.truevault.com' const token = 'token123' const user = { patient: { username: 'christopher@aitmed.com', password: 'abc123', user_id: 'userid123', tv_uid: 'tv_uid123', tv_token: 'tv_token123', accessToken: 'accessToken123', }, provider: { user_id: 'userid123', tv_uid: 'tv_uid123', tv_api_key: 'b6f6b742-14fa-4f57-9f1a-731f36e09323', email: 'bb123@gmail.com', password: 'Breezep1@', first_name: 'Stan', NPI: 'npi123', }, } let client: any beforeEach(() => { client = aitmedApi({ env: 'testapi', tvKeys }) }) afterEach(() => { nock.cleanAll() }) // login('provider', { email, password }) // login('provider', { tv_uid, tv_token }) describe('aitmedApi', () => { it('should throw if option tvKeys was not provided', () => { const init = () => aitmedApi({ env: 'testapi' }) expect(init).to.throw() }) it('should initialize _creds when option tvKeys is provided', () => { const _client = aitmedApi({ env: 'testapi', tvKeys }) const creds = _client.getTvCreds() expect(creds).to.equal(tvKeys) }) describe('.activateProvider and .approveProvider', () => { beforeEach(() => { nock(baseURL) .get('/v1/account/provider/provider123/approve/') .reply(200, { result: { user_id: 'provider123', is_approved: true }, }) }) it('should throw if the userId parameter is undefined', () => { client.setAccountType('admin') return expect(client.activateProvider()).to.eventually.be.rejectedWith( E.MissingParametersError, ) }) it('should return the updated profile object with is_approved equal to false if success', () => { client.setAccountType('admin') return expect( client.approveProvider('provider123'), ).to.eventually.include({ is_approved: true, }) }) }) describe('.completeAppointment', () => { // it('should throw if the appointment id is not a valid type', () => { // client.setAccountType('patient') // const apptId = '9b985930-fbd2-4243-b094-1186ccfc11ad' // return client // .login('patient', { // username: 'christopher@aitmed.com', // password: 'Breezep1@', // }) // .then(() => { // return client // .completeAppointment(apptId) // .then((result: any) => { // console.log(result) // }) // .catch(console.error) // }) // }) it('should return back the completed appointment object on success', () => {}) }) describe('.confirmEmail', () => { it('should throw with an InvalidParametersError error if the key parameter is invalid', () => { client.setAccountType('guest') return expect(client.confirmEmail(null)).to.eventually.be.rejectedWith( E.InvalidParametersError, /The key is not a valid type/i, ) }) it('should return a "success" string if the call was successful', () => { nock(baseURL) .get('/v1/account/confirm_email/') .reply(200, { result: 'success' }) client.setAccountType('guest') return expect(client.confirmEmail('fdsfdsfsd')).to.eventually.equal( 'success', ) }) }) // describe('.createAppointment', () => { // it('should reject if the current accountType is not a patient', () => { // const params = { // provider: '2019-03-31T20:53:21.964Z', // purpose: 'idk', // specialty: 'FAMILY_MEDICINE', // payment_profile_id: '32432', // time_slot: 5353, // charge_method: 'CHASE', // } // client.setAccountType('marketer') // return expect( // client.createAppointment(params), // ).to.eventually.be.rejectedWith(E.WrongAccountTypeError) // }) // it('should reject if patient parameter is not passed in', () => { // const params = { // provider: '2019-03-31T20:53:21.964Z', // purpose: 'idk', // specialty: 'FAMILY_MEDICINE', // payment_profile_id: '32432', // time_slot: 5353, // charge_method: 'CHASE', // } // client.setAccountType('patient') // return expect( // client.createAppointment(params), // ).to.eventually.be.rejectedWith( // E.InvalidParametersError, // /"patient" parameter is required/i, // ) // }) // it('should reject if provider parameter is not passed in', () => { // const params = { // patient: 'CA', // purpose: 'idk', // specialty: 'FAMILY_MEDICINE', // payment_profile_id: '32432', // time_slot: 5353, // charge_method: 'CHASE', // } // client.setAccountType('patient') // return expect( // client.createAppointment(params), // ).to.eventually.be.rejectedWith( // E.InvalidParametersError, // /"provider" parameter is required/i, // ) // }) // it('should reject if specialty parameter is not passed in', () => { // const params = { // patient: 'CA', // provider: '2019-03-31T20:53:21.964Z', // purpose: 'idk', // payment_profile_id: '32432', // time_slot: 5353, // charge_method: 'CHASE', // } // client.setAccountType('patient') // return expect( // client.createAppointment(params), // ).to.eventually.be.rejectedWith( // E.InvalidParametersError, // /"specialty" parameter is required/i, // ) // }) // it('should return an object with the shape { pagination, appointments, ids } if success', () => { // const params = { // patient: 'asfasfsafas', // provider: 'safasfasfsa', // specialty: 'FAMILY_MEDICINE', // purpose: 'idk', // payment_profile_id: '32432', // time_slot: 5353, // charge_method: 'CHASE', // } // const response = { // id: 'fsdfds', // created_at: '2019-04-24T17:27:47.125220Z', // creator: 'bf93c1be-d119-4230-b6eb-3aaefb56033d', // patient: { user_id: 'asfasfsafas' }, // provider: { user_id: 'safasfasfsa' }, // time_slot: 5353, // purpose: 'idk', // } // nock(baseURL) // .post('/v1/appointment/', params) // .reply(200, { result: response }) // return client // .setAccountType('patient') // .createAppointment(params) // .then((result: any) => { // expect(result.id).not.to.be.undefined // expect(result.patient).not.to.be.undefined // expect(result.provider).not.to.be.undefined // expect(result.purpose).not.to.be.undefined // expect(result.time_slot).not.to.be.undefined // }) // }) // it('should throw if payment_profile_id isnt provided and time_slot is not provided', () => { // const params = { // patient: 'CA', // provider: '2019-03-31T20:53:21.964Z', // specialty: 'FAMILY_MEDICINE', // purpose: 'idk', // charge_method: 'CHASE', // coupons: [], // card_number: 4111111111111111, // expiration_date: '2020-10', // cvv_code: 900, // billing_first_name: 'Sitong', // billing_last_name: 'Ge', // billing_address: '258 North Green Springs Road', // billing_city: 'Indianapolis', // billing_state: 'IN', // billing_zip_code: 4621, // } // client.setAccountType('patient') // return expect( // client.createAppointment(params), // ).to.eventually.be.rejectedWith( // E.InvalidParametersError, // /"time_slot" parameter is required/i, // ) // }) // it('should throw if charge_method is not provided', () => { // const params = { // patient: 'CA', // provider: '2019-03-31T20:53:21.964Z', // specialty: 'FAMILY_MEDICINE', // purpose: 'idk', // time_slot: 5353, // coupons: [], // card_number: 4111111111111111, // expiration_date: '2020-10', // cvv_code: 900, // billing_first_name: 'Sitong', // billing_last_name: 'Ge', // billing_address: '258 North Green Springs Road', // billing_city: 'Indianapolis', // billing_state: 'IN', // billing_zip_code: 4621, // } // client.setAccountType('patient') // return expect( // client.createAppointment(params), // ).to.eventually.be.rejectedWith( // E.InvalidParametersError, // /"charge_method" parameter is required/i, // ) // }) // it('should throw if payment_profile_id is undefined and card_number is not provided', () => { // const params = { // patient: 'CA', // provider: '2019-03-31T20:53:21.964Z', // specialty: 'FAMILY_MEDICINE', // purpose: 'idk', // time_slot: 5353, // coupons: [], // charge_method: 'CHASE', // expiration_date: '2020-10', // cvv_code: 900, // billing_first_name: 'Sitong', // billing_last_name: 'Ge', // billing_address: '258 North Green Springs Road', // billing_city: 'Indianapolis', // billing_state: 'IN', // billing_zip_code: 4621, // } // client.setAccountType('patient') // return expect( // client.createAppointment(params), // ).to.eventually.be.rejectedWith( // E.InvalidParametersError, // /"card_number" parameter is required/i, // ) // }) // it('should throw if payment_profile_id is undefined and expiration_date is not provided', () => { // const params = { // patient: 'CA', // provider: '2019-03-31T20:53:21.964Z', // specialty: 'FAMILY_MEDICINE', // purpose: 'idk', // time_slot: 5353, // coupons: [], // charge_method: 'CHASE', // card_number: '2020-10', // cvv_code: 900, // billing_first_name: 'Sitong', // billing_last_name: 'Ge', // billing_address: '258 North Green Springs Road', // billing_city: 'Indianapolis', // billing_state: 'IN', // billing_zip_code: 4621, // } // client.setAccountType('patient') // return expect( // client.createAppointment(params), // ).to.eventually.be.rejectedWith( // E.InvalidParametersError, // /"expiration_date" parameter is required/i, // ) // }) // it('should throw if payment_profile_id is undefined and cvv_code is not provided', () => { // const params = { // patient: 'CA', // provider: '2019-03-31T20:53:21.964Z', // specialty: 'FAMILY_MEDICINE', // purpose: 'idk', // time_slot: 5353, // coupons: [], // charge_method: 'CHASE', // card_number: '2020-10', // expiration_date: '900', // billing_first_name: 'Sitong', // billing_last_name: 'Ge', // billing_address: '258 North Green Springs Road', // billing_city: 'Indianapolis', // billing_state: 'IN', // billing_zip_code: 4621, // } // client.setAccountType('patient') // return expect( // client.createAppointment(params), // ).to.eventually.be.rejectedWith( // E.InvalidParametersError, // /"cvv_code" parameter is required/i, // ) // }) // it('should throw if payment_profile_id is undefined and billing_first_name is not provided', () => { // const params = { // patient: 'CA', // provider: '2019-03-31T20:53:21.964Z', // specialty: 'FAMILY_MEDICINE', // purpose: 'idk', // time_slot: 5353, // coupons: [], // charge_method: 'CHASE', // card_number: '2020-10', // expiration_date: '900', // cvv_code: 950, // billing_last_name: 'Ge', // billing_address: '258 North Green Springs Road', // billing_city: 'Indianapolis', // billing_state: 'IN', // billing_zip_code: 4621, // } // client.setAccountType('patient') // return expect( // client.createAppointment(params), // ).to.eventually.be.rejectedWith( // E.InvalidParametersError, // /"billing_first_name" parameter is required/i, // ) // }) // it('should throw if payment_profile_id is undefined and billing_last_name is not provided', () => { // const params = { // patient: 'CA', // provider: '2019-03-31T20:53:21.964Z', // specialty: 'FAMILY_MEDICINE', // purpose: 'idk', // time_slot: 5353, // coupons: [], // charge_method: 'CHASE', // card_number: '2020-10', // expiration_date: '900', // cvv_code: 950, // billing_first_name: 'Ge', // billing_address: '258 North Green Springs Road', // billing_city: 'Indianapolis', // billing_state: 'IN', // billing_zip_code: 4621, // } // client.setAccountType('patient') // return expect( // client.createAppointment(params), // ).to.eventually.be.rejectedWith( // E.InvalidParametersError, // /"billing_last_name" parameter is required/i, // ) // }) // it('should throw if payment_profile_id is undefined and billing_address is not provided', () => { // const params = { // patient: 'CA', // provider: '2019-03-31T20:53:21.964Z', // specialty: 'FAMILY_MEDICINE', // purpose: 'idk', // time_slot: 5353, // coupons: [], // charge_method: 'CHASE', // card_number: '2020-10', // expiration_date: '900', // cvv_code: 950, // billing_first_name: 'Ge', // billing_last_name: '258 North Green Springs Road', // billing_city: 'Indianapolis', // billing_state: 'IN', // billing_zip_code: 4621, // } // client.setAccountType('patient') // return expect( // client.createAppointment(params), // ).to.eventually.be.rejectedWith( // E.InvalidParametersError, // /"billing_address" parameter is required/i, // ) // }) // it('should throw if payment_profile_id is undefined and billing_city is not provided', () => { // const params = { // patient: 'CA', // provider: '2019-03-31T20:53:21.964Z', // specialty: 'FAMILY_MEDICINE', // purpose: 'idk', // time_slot: 5353, // coupons: [], // charge_method: 'CHASE', // card_number: '2020-10', // expiration_date: '900', // cvv_code: 950, // billing_first_name: 'Ge', // billing_last_name: '258 North Green Springs Road', // billing_address: 'Indianapolis', // billing_state: 'IN', // billing_zip_code: 4621, // } // client.setAccountType('patient') // return expect( // client.createAppointment(params), // ).to.eventually.be.rejectedWith( // E.InvalidParametersError, // /"billing_city" parameter is required/i, // ) // }) // it('should throw if payment_profile_id is undefined and billing_state is not provided', () => { // const params = { // patient: 'CA', // provider: '2019-03-31T20:53:21.964Z', // specialty: 'FAMILY_MEDICINE', // purpose: 'idk', // time_slot: 5353, // coupons: [], // charge_method: 'CHASE', // card_number: '2020-10', // expiration_date: '900', // cvv_code: 950, // billing_first_name: 'Ge', // billing_last_name: '258 North Green Springs Road', // billing_address: 'Indianapolis', // billing_city: 'IN', // billing_zip_code: 4621, // } // client.setAccountType('patient') // return expect( // client.createAppointment(params), // ).to.eventually.be.rejectedWith( // E.InvalidParametersError, // /"billing_state" parameter is required/i, // ) // }) // it('should throw if payment_profile_id is undefined and billing_zip_code is not provided', () => { // const params = { // patient: 'CA', // provider: '2019-03-31T20:53:21.964Z', // specialty: 'FAMILY_MEDICINE', // purpose: 'idk', // time_slot: 5353, // coupons: [], // charge_method: 'CHASE', // card_number: '2020-10', // expiration_date: '900', // cvv_code: 950, // billing_first_name: 'Ge', // billing_last_name: '258 North Green Springs Road', // billing_address: 'Indianapolis', // billing_city: 'IN', // billing_state: 'CA', // } // client.setAccountType('patient') // return expect( // client.createAppointment(params), // ).to.eventually.be.rejectedWith( // E.InvalidParametersError, // /"billing_zip_code" parameter is required/i, // ) // }) // it('should throw if coupons is provided but it is not a string or an array', () => { // const params = { // patient: 'CA', // provider: '2019-03-31T20:53:21.964Z', // specialty: 'FAMILY_MEDICINE', // purpose: 'idk', // time_slot: 5353, // coupons: 432432, // charge_method: 'CHASE', // card_number: '2020-10', // expiration_date: '900', // cvv_code: 950, // billing_first_name: 'Ge', // billing_last_name: '258 North Green Springs Road', // billing_address: 'Indianapolis', // billing_city: 'IN', // billing_state: 'CA', // billing_zip_code: 434343, // } // client.setAccountType('patient') // return expect( // client.createAppointment(params), // ).to.eventually.be.rejectedWith( // TypeError, // /"coupons" parameter is not a string or array/i, // ) // }) // }) describe('.createPatient', () => { beforeEach(() => { nock(baseTvURL) .post('/v1/users') .reply(200, { user: { user_id: 'user123', access_token: 'atoken123' } }) nock(baseURL) .post('/v1/account/patient/') .reply(200, { result: { user_id: 'user123', tv_uid: '1f5dae2b-bf17-4a25-a119-058fef048b54', tv_group_id: 'd70930cf-0996-430c-9a89-872524ea7e68', inviter_code: 'wyFTfg', activation_key: 'Imfs7kjGY', }, }) }) const reqKeys = [ 'user_id', 'tv_uid', 'tv_group_id', 'inviter_code', 'activation_key', ] const createPatientArgs = [ 'am@gmail.com', 'c', { languages: [{ code: 'en-US', is_primary: true }] }, ] it('`should set the accountType to patient if true`vault call was successful', () => { return client.createPatient(...createPatientArgs).then(() => { const accountType = client.getCurrentAccountType() expect(accountType).to.equal('patient') }) }) it('should create the patient and return the results', () => { return expect( client.createPatient(...createPatientArgs), ).to.eventually.have.all.keys(reqKeys) }) }) describe('createPatientMember', () => { it('should throw with TypeError if username or password is invalid type') }) describe('.createPatientBlob', () => { const blobInfo = { patient: 'pt123', tv_blob_ids: 'id123', filename: 'hi.pdf', created: '2019-04-05T04:54:59.069Z', } it('should throw if the argument is undefined', () => { client.setAccountType('patient') return expect(client.createPatientBlob()).to.eventually.be.rejectedWith( E.MissingParametersError, /missing/i, ) }) it('should throw if the argument is valid but not an object', () => { client.setAccountType('patient') return expect( client.createPatientBlob('abc123'), ).to.eventually.be.rejectedWith(TypeError, /not an object/i) }) it('should throw if the tv_blob_ids is undefined', () => { client.setAccountType('patient') return expect( client.createPatientBlob({ ...blobInfo, tv_blob_ids: undefined }), ).to.eventually.be.rejectedWith(TypeError) }) it('should throw if the filename is undefined', () => { client.setAccountType('patient') return expect( client.createPatientBlob({ ...blobInfo, filename: undefined }), ).to.eventually.be.rejectedWith(TypeError) }) it('should throw if the patient user_id is undefined', () => { client.setAccountType('patient') return expect( client.createPatientBlob({ ...blobInfo, patient: undefined }), ).to.eventually.be.rejectedWith(TypeError) }) }) describe('.createAppointmentReview', () => { const args = { appointment: 'appt123', rating: 5, comment: 'you rock!' } beforeEach(() => { nock(baseURL) .post('/v1/appointment_review/') .reply(201, { result: args }) }) it('should reject if the accountType is not set to patient', () => { client.setAccountType('provider') return expect( client.createAppointmentReview(args), ).to.eventually.be.rejectedWith(E.WrongAccountTypeError, /Only patients/i) }) it('should reject if the appointment param is invalid', () => { client.setAccountType('patient') return expect( client.createAppointmentReview({ ...args, appointment: null }), ).to.eventually.be.rejectedWith( TypeError, /"appointment" parameter is invalid/i, ) }) it('should reject if the rating param is invalid', () => { client.setAccountType('patient') return expect( client.createAppointmentReview({ ...args, rating: null }), ).to.eventually.be.rejectedWith( TypeError, /"rating" parameter is invalid/i, ) }) it('should reject if the comment param is invalid', () => { client.setAccountType('patient') return expect( client.createAppointmentReview({ ...args, comment: null }), ).to.eventually.be.rejectedWith( TypeError, /"comment" parameter is invalid/i, ) }) it('should return an object with shape { appointment, rating, comment } on success', () => { client.setAccountType('patient') return expect( client.createAppointmentReview(args), ).to.eventually.have.all.keys('appointment', 'rating', 'comment') }) it('should convert the rating param to 5 if the value is higher than that', () => { nock.cleanAll() nock(baseURL) .post('/v1/appointment_review/') .reply(201, { result: { ...args, rating: 5 } }) client.setAccountType('patient') return expect( client.createAppointmentReview({ ...args, rating: 10 }), ).to.eventually.include({ rating: 5 }) }) it('should convert the rating param to 0 if the value is less than 0', () => { nock.cleanAll() nock(baseURL) .post('/v1/appointment_review/') .reply(201, { result: { ...args, rating: 0 } }) client.setAccountType('patient') return expect( client.createAppointmentReview({ ...args, rating: -10 }), ).to.eventually.include({ rating: 0 }) }) }) describe('.deleteChasePaymentProfile', () => { it('should return "success" on success', () => { nock(baseURL) .delete('/v1/payment/chase_payment_profile/183901223/') .reply(204, { result: 'success', }) client.setAccountType('patient') return expect( client.deleteChasePaymentProfile(183901223), ).to.eventually.equal('success') }) }) describe('.deletePatientBlob', () => { it('should throw if the accountType is not a patient', () => { client.setAccountType('provider') return expect( client.deletePatientBlob('fff'), ).to.eventually.be.rejectedWith(E.WrongAccountTypeError) }) it('should return a "success" string if the call was successful', () => { nock(baseURL) .delete('/v1/account/patient_blob/blobId123/') .reply(200, { status: 'success', result: null }) return client .setAccountType('patient') .deletePatientBlob('blobId123') .then((result: any) => { expect(result).to.equal('success') }) }) it('should throw with a MissingParametersError if id is undefined', () => { client.setAccountType('patient') return expect(client.deletePatientBlob()).to.eventually.be.rejectedWith( E.MissingParametersError, ) }) }) describe('.getCurrentAccountType', () => { it('Should return the current accountType', () => { client.setAccountType('provider') const accountType = client.getCurrentAccountType() expect(accountType).to.equal('provider') }) }) describe('.getPreviousApiCalls', () => { it('should return the previous API calls from the internal store', () => { nock(baseURL) .delete('/v1/account/patient_blob/blobId123/') .reply(200, { status: 'success', result: null }) return client .setAccountType('patient') .deletePatientBlob('blobId123') .then(() => { const prevCalls = client.getPreviousApiCalls() expect(prevCalls).to.include.members([ `/account/patient_blob/blobId123/`, ]) }) }) }) describe('.fetchAppointment', () => { it('Should return the appointment object', () => { const appointmentId = '005463f6-edc6-44aa-9d99-f83e333398fe' nock(baseURL) .get(`/v1/appointment/${appointmentId}/`) .reply(200, { status: 'success', result: { id: appointmentId, patient: { user_id: 'user123' }, provider: { email: user.provider.email, status: 2 }, start_time: '2019-04-09T02:00:00Z', end_time: '2019-04-09T02:15:00Z', }, }) return client .setAccountType('provider') .fetchAppointment(appointmentId) .then((result: types.Appointment) => { const keys = Object.keys(result) expect(keys).to.have.members([ 'id', 'patient', 'provider', 'start_time', 'end_time', ]) }) }) }) describe('.fetchAppointmentReview', () => { it('Should return the appointment review object', () => { const reviewId = 'aaaaa' const result = { appointment: 'ap_n28hfh9q924', rating: '5', comment: 'The best doc ever seen!', } nock(baseURL) .get(`/v1/appointment_review/${reviewId}/`) .reply(205, { status: 'success', result }) client.setAccountType('provider') return expect( client.fetchAppointmentReview(reviewId), ).to.eventually.include(result) }) it('should return a rejected promise if the id parameter is invalid', () => { client.setAccountType('provider') return expect( client.fetchAppointmentReview(null), ).to.eventually.be.rejectedWith( E.InvalidParametersError, 'review "id" is invalid', ) }) }) describe('.fetchAppointmentReviews', () => { it('should return a rejected promise if the userId parameter is invalid', () => { client.setAccountType('provider') return expect( client.fetchAppointmentReviews(null), ).to.eventually.be.rejectedWith( E.InvalidParametersError, /provider user id is not a valid string/i, ) }) it('should return a rejected promise if the userId parameter is a valid javascript value but not a string', () => { client.setAccountType('provider') return expect( client.fetchAppointmentReviews([]), ).to.eventually.be.rejectedWith( E.InvalidParametersError, /"userId" parameter is not a string/i, ) }) it('should return an object with pagination and an array of the providers reviews on success', () => { const review1 = { appointment: 'ap123', rating: 1, comment: 'yeah' } const review2 = { appointment: 'af123', rating: 4, comment: 'apple' } nock(baseURL) .get('/v1/appointment_review/?provider_id=userid123') .reply(200, { result: { pagination: {}, data: [review1, review2] } }) client.setAccountType('provider') return expect( client.fetchAppointmentReviews('userid123'), ).to.eventually.include.all.keys('pagination', 'reviews', 'ids') }) }) describe('.fetchCategories', () => { it('should fetch and return the categories', () => { const result = [ { code: 'MEDICAL', translations: { 'en-US': 'Medical', sub_categories: [], specialties: [ { code: 'FAMILY_MEDICINE', category: 'MEDICAL', type: 'COMMON', translations: { 'en-US': 'Family Medicine' }, }, ], }, }, ] nock(baseURL) .get('/v1/info/categories/') .reply(200, { result }) return client .setAccountType('provider') .fetchCategories() .then((_result: any[]) => { expect(Array.isArray(_result)).to.equal(true) expect(result[0].code).to.equal('MEDICAL') }) }) }) describe('.fetchCoupons', () => { it('should return an array of objects with shape { code, amount, expired_at }', () => { nock(baseURL) .get('/v1/payment/coupon/') .reply(200, { status: 'success', result: [ { code: 'MPJ8VLVVMKUWNGWVQL87V8O9V2TJN5KX', amount: 6900, expired_at: '2019-11-10T21:35:18.853801Z', }, ], }) return client .setAccountType('patient') .fetchCoupons() .then((result: any) => { expect(Array.isArray(result)).to.be.true expect(result[0].code).not.to.be.undefined expect(result[0].amount).not.to.be.undefined expect(result[0].expired_at).not.to.be.undefined }) }) it('should throw if the accountType using this method is not a patient', () => { client.setAccountType('provider') return expect(client.fetchCoupons()).to.eventually.be.rejectedWith( E.WrongAccountTypeError, ) }) }) describe('.fetchDwollaToken', () => { it('should the token as a string on success', () => { nock(baseURL) .get('/v1/payment/dwolla/iav_token/') .reply(200, { status: 'success', result: 'g2aLRhCZE5CqRM1Kb4Eda0EMZGDNcPGbP9uS0s6F9YJxAaaDyZ', }) client.setAccountType('patient') return expect(client.fetchDwollaToken()).to.eventually.equal( 'g2aLRhCZE5CqRM1Kb4Eda0EMZGDNcPGbP9uS0s6F9YJxAaaDyZ', ) }) }) describe('.fetchGenders', () => { it('should fetch and return the genders', () => { const result = [ { code: 'MALE', translations: { 'en-US': 'Male', 'zh-CN': '男', }, }, ] nock(baseURL) .get('/v1/info/gender/') .reply(200, { result }) return client .setAccountType('provider') .fetchGenders() .then((_result: any[]) => { expect(Array.isArray(_result)).to.equal(true) expect(Object.keys(_result[0])).to.include.members([ 'code', 'translations', ]) }) }) }) describe('.fetchLanguages', () => { it('should fetch and return the languages', () => { const result = [ { code: 'en-US', english: 'English', translated: 'English', }, ] nock(baseURL) .get('/v1/info/languages/') .reply(200, { result }) return client .setAccountType('provider') .fetchLanguages() .then((_result: any[]) => { expect(Array.isArray(_result)).to.equal(true) expect(Object.keys(_result[0])).to.include.members([ 'code', 'english', 'translated', ]) }) }) }) describe('.fetchPatient', () => { it('should fetch and return the patient object', () => { nock(baseURL) .get('/v1/account/patient/userid123/') .reply(200, { data: { user_id: 'userid123', tv_uid: 'tv_uid123' } }) return client .setAccountType('patient') .fetchPatient('userid123') .then((response: any) => { expect(response.user_id).to.equal('userid123') expect(response.tv_uid).to.equal('tv_uid123') }) }) }) describe('.fetchPatientBlob', () => { it('should fetch and return a blob object', () => { nock(baseURL) .get('/v1/account/patient_blob/a/') .reply(200, { result: { tv_blob_ids: 'a', filename: 'b.pdf', created: 'c', patient: 'd', }, }) return client .setAccountType('patient') .fetchPatientBlob('a') .then((blobObj: any) => { expect(blobObj.tv_blob_ids).to.equal('a') expect(blobObj.filename).to.equal('b.pdf') expect(blobObj.created).to.equal('c') expect(blobObj.patient).to.equal('d') }) }) }) describe('.fetchPatientBlobs', () => { it( 'should fetch and return an object with shape { pagination, blobs, userIds } ' + 'on success if passed in one user_id string', () => { nock(baseURL) .get('/v1/account/patient_blob/?patient=stuff') .reply(200, { result: { pagination: { object_count: 1 }, data: [ { tv_blob_ids: 'a', filename: 'b.pdf', created: 'c', patient: 'd', }, ], }, }) return client .setAccountType('patient') .fetchPatientBlobs('stuff') .then(({ pagination, blobs, ids }: any) => { expect(pagination).to.not.be.undefined expect(blobs).to.not.be.undefined expect(ids).to.not.be.undefined expect(Object.keys(blobs).length).to.equal(1) }) }, ) it( 'should fetch and return an object with shape { pagination, blobs, ids } on ' + 'success if passed in an array of user_id strings', () => { nock(baseURL) .get( '/v1/account/patient_blob/?patient=stuff&patient=soda&patient=pepsi', ) .reply(200, { result: { pagination: { object_count: 2 }, data: [ { tv_blob_ids: 'asdaa', filename: 'b.pdf', created: 'c', patient: 'd', }, { tv_blob_ids: 'sadf', filename: 'b.pdf', created: 'c', patient: 'd', }, ], }, }) return client .setAccountType('patient') .fetchPatientBlobs(['stuff', 'soda', 'pepsi']) .then(({ pagination, blobs, ids }: any) => { expect(pagination).to.not.be.undefined expect(blobs).to.not.be.undefined expect(ids).to.not.be.undefined // expect(Object.keys(blobs).length).to.equal(2) }) }, ) }) describe('.fetchPatientDocument', () => { const getUrl = (id: string) => `https://api.truevault.com/v1/vaults/vault123/documents/${id}` const method = 'get' it( 'shoud return a rejected InvalidParamersError promise if the document id is invalid', ) it( 'shoud return a rejected InvalidParamersError promise if the document id is not a string type', ) it('should return the patient document if success') }) describe('.fetchPatientDocuments', () => { const getUrl = (id: string) => `https://api.truevault.com/v1/vaults/vault123/documents/${id}` const method = 'get' it( 'shoud return a rejected InvalidParamersError promise if the document ids are invalid type', ) it( 'shoud return a rejected InvalidParamersError promise if the document ids parameter is not an array type', ) it('should return the normalized patient documents if success') }) describe('fetchPatientMembers', () => { it('should throw if tvUids is not a string or array', () => { client.setAccountType('patient') return expect( client.fetchPatientMembers(55), ).to.eventually.be.rejectedWith(E.InvalidParametersError) }) }) describe('.fetchProviders', () => { beforeEach(() => { nock(baseURL) .get('/v1/account/provider/') .reply(200, { data: [ { user_id: 'aaaa', state: 'AL' }, { user_id: 'bbbb', state: 'CA' }, ], pagination: {}, }) }) it('should return the resulting data in a normalized data structure for fast object lookups', () => { client.setAccountType('admin') return client.fetchProviders().then((result: any) => { expect(Array.isArray(result.ids)).to.be.true expect(result.pagination).to.not.be.undefined expect(result.providers).to.not.be.undefined expect(Object.keys(result.providers).length).to.be.greaterThan(0) }) }) it('should throw if name is not undefined and is not an array or object', () => { client.setAccountType('admin') return expect( client.fetchProviders({ name: 500 }), ).to.eventually.be.rejectedWith(TypeError) }) it('should throw if name is an empty array', () => { client.setAccountType('admin') return expect( client.fetchProviders({ name: [] }), ).to.eventually.be.rejectedWith(Error) }) it("should throw if name is an object but doesn't contain any of the properties: firstName, middleName, lastName", () => { client.setAccountType('admin') return expect( client.fetchProviders({ name: { fruit: 'apple' } }), ).to.eventually.be.rejectedWith(E.MissingParametersError) }) }) describe('.fetchSpecialties', () => { it('should return an object with shape { specialties, ids }', () => { const specialties = [ { code: 'PULMONOLOGY', category: 'SPECIALIST', type: 'PROFESSION', translations: { 'en-US': 'Pulmonology', }, }, { code: 'EAR_NOSE_THROAT', category: 'SPECIALIST', type: 'PROFESSION', translations: { 'en-US': 'Ear Nose Throat', }, }, ] nock(baseURL) .get('/v1/info/specialties/') .reply(200, { result: specialties }) client.setAccountType('provider') return expect(client.fetchSpecialties()).to.eventually.have.all.keys( 'specialties', 'ids', ) }) }) describe('.fetchUpcomingAppointments', () => { it('Should fetch and return the results in the shape { pagination, ids, appointments }', () => { nock(baseURL) .get('/v1/appointment/?status=1&status=2&limit=10') .reply(200, { result: { pagination: { object_count: 0, page_limit: 10, page_index: 1, num_pages: 1, }, data: [{ id: 'appointment1' }, { id: 'appointment2' }], }, }) return client .setAccountType('provider') .fetchUpcomingAppointments({ limit: 10 }) .then((result: types.FetchAppointmentsReturnObject) => { expect(result.pagination).not.to.be.undefined expect(result.ids).not.to.be.undefined expect(result.appointments).not.to.be.undefined }) }) it('The optional filter param should be able to filter the results if used', () => { nock(baseURL) .get(`/v1/appointment/?status=1&status=2&limit=10`) .reply(200, { result: { pagination: {}, data: [ { id: 'a1', is_walk_in: true }, { id: 'a2', is_walk_in: false }, { id: 'a3', is_walk_in: true }, { id: 'a4', is_walk_in: false }, { id: 'a5', is_walk_in: true }, { id: 'a6', is_walk_in: false }, ], }, }) const filter = (appt: types.Appointment) => appt.is_walk_in !== false return client .setAccountType('provider') .fetchUpcomingAppointments({ limit: 10, filter }) .then( ({ appointments, }: { appointments: { [id: string]: types.Appointment } }) => { const ids = Object.keys(appointments) expect(ids).to.have.lengthOf(3) ids.forEach((id) => expect(appointments[id].is_walk_in).to.be.true) }, ) }) }) describe('.findProviders', () => { it('should return a rejected promise if the accountType using this method is not a patient', () => { const obj1 = { state: 'CA', specialty: 'PSYCHIATRIST', } client.setAccountType('provider') return expect(client.findProviders(obj1)).to.eventually.be.rejectedWith( E.WrongAccountTypeError, /Only patients can use this URI/i, ) }) it('should reject if the time parameter is not passed in', () => { const obj1 = { state: 'CA', specialty: 'PSYCHIATRIST', } client.setAccountType('patient') return expect(client.findProviders(obj1)).to.eventually.be.rejectedWith( E.InvalidParametersError, /"time" parameter is required/i, ) }) it('should reject if the state paremeter is not passed in', () => { const obj1 = { specialty: 'PSYCHIATRIST', time: '2019-03-31T20:53:21.964Z', } client.setAccountType('patient') return expect(client.findProviders(obj1)).to.eventually.be.rejectedWith( E.InvalidParametersError, /"state" parameter is required/i, ) }) it('should reject if the speciality paremeter is not passed in', () => { const obj1 = { state: 'CA', time: '2019-03-31T20:53:21.964Z', } client.setAccountType('patient') return expect(client.findProviders(obj1)).to.eventually.be.rejectedWith( E.InvalidParametersError, /"specialty" parameter is required/i, ) }) it('should return the results if successful in the shape of { pagination, providers, timeSlotIds }', () => { const data = [ { time_slot_id: 309, start: 'f', end: 'b', provider: { email: 'bb123@gmail.com' }, }, { time_slot_id: 1500, start: 'f', end: 'b', provider: { email: 'bb123@gmail.com' }, }, { time_slot_id: 987, start: 'f', end: 'b', provider: { email: 'bb123@gmail.com' }, }, ] const params = { specialty: 'FAMILY_MEDICINE', state: 'CA', time: '2019-03-31T20:53:21.964Z', } nock(baseURL) .get( '/v1/appointment/find_provider/?specialty=FAMILY_MEDICINE&state=CA&time=2019-03-31T20:53:21.964Z', ) .reply(200, { result: { pagination: {}, data } }) client.setAccountType('patient') return client.findProviders(params).then((value: any) => { expect(value.pagination).not.to.be.undefined expect(value.providers).not.to.be.undefined expect(Array.isArray(value.timeSlotIds)).to.be.true }) }) }) describe('.findProviderAvailabilities', () => { it('should return a rejected promise if the accountType using this method is not a patient', () => { const obj1 = { state: 'CA', specialty: 'PSYCHIATRIST', } client.setAccountType('provider') return expect( client.findProviderAvailabilities(obj1), ).to.eventually.be.rejectedWith( E.WrongAccountTypeError, /Only patients can use this URI/i, ) }) it('should reject if time parameter is not passed in', () => { const obj1 = { state: 'CA', specialty: 'PSYCHIATRIST', } client.setAccountType('patient') return expect( client.findProviderAvailabilities(obj1), ).to.eventually.be.rejectedWith( E.InvalidParametersError, /"time" parameter is required/i, ) }) it('should reject if state paremeter is not passed in', () => { const obj1 = { specialty: 'PSYCHIATRIST', time: '2019-03-31T20:53:21.964Z', } client.setAccountType('patient') return expect( client.findProviderAvailabilities(obj1), ).to.eventually.be.rejectedWith( E.InvalidParametersError, /"state" parameter is required/i, ) }) it('should return the results if successful in the shape of { pagination, providers, timeSlotIds }', () => { const response = { pagination: {}, data: { user_id: 'userid123', email: 'bb123@@gmail.com', time_slots: [ { id: 42344, start_time: '2019-03-31T22:39:33.229Z', end_time: '2019-04-04T22:39:33.229Z', }, { id: 342, start_time: '2019-05-02T22:39:33.229Z', end_time: '2019-05-22T22:39:33.229Z', }, { id: 88889, start_time: '2019-03-31T22:39:33.229Z', end_time: '2019-04-15T22:39:33.229Z', }, ], }, } const params = { time: '2019-03-31T22:39:33.229Z', state: 'CA', } nock(baseURL) .get( '/v1/appointment/find_provider_availability/?time=2019-03-31T22:39:33.229Z&state=CA', ) .reply(200, { result: response }) client.setAccountType('patient') return client.findProviderAvailabilities(params).then((value: any) => { expect(value.pagination).not.to.be.undefined expect(value.providers).not.to.be.undefined expect(Array.isArray(value.ids)).to.be.true expect(value.ids.length).to.equal(3) }) }) }) describe('.resetPassword', () => { it('should return a string of "success" if the call was a success', () => { nock(baseURL) .post('/v1/account/reset_password/') .reply(200, { result: null }) return expect( client.resetPassword('somekey', 'somepw'), ).to.eventually.equal('success') }) }) describe('.forgotPassword', () => { describe('patients', () => { it('should return a string value of "success" if the call was successful') // it('should return a string value of "success" if the call was successful', () => { // const username = 'hi@gmail.com' // const tvId = 'uid123' // const tvToken = 'accessToken123' // nock(baseTvURL) // .post(`/v1/password_reset_flows/${username}`, username) // .reply(200, { result: 'success', transaction_id: 'a123' }) // nock(baseTvURL) // .post(`/v1/password_reset_flows`, username) // .reply(200, { result: 'success', transaction_id: 'a123' }) // client.setAccountType('patient') // return expect(client.forgotPassword(username)).to.eventually.equal( // 'success', // ) // }) it( 'should throw if the username parameter is a valid type but not a string', ) }) describe('non-patients', () => { it('should throw if the email parameter is a valid type but not a string', () => { client.setAccountType('provider') return expect( client.forgotPassword(5003), ).to.eventually.be.rejectedWith( TypeError, /email parameter is not a string/i, ) }) it('should return the "Email sent" if the call was a success', () => { nock(baseURL) .post('/v1/account/provider/forgot_password/', { email: 'f@gmail.com', }) .reply(200, { result: 'Email has sent' }) client.setAccountType('provider') return expect(client.forgotPassword('f@gmail.com')).to.eventually.equal( 'Email sent', ) }) it('should return a rejected promise if the accountType is "guest"', () => { client.setAccountType('guest') return expect( client.forgotPassword('f@gmail.com'), ).to.eventually.be.rejectedWith( E.WrongAccountTypeError, /guests cannot reset/i, ) }) }) }) describe('.forgotPasswordProvider', () => { it('should return a string of "success" if the call was a success', () => { nock(baseURL) .post('/v1/account/provider/forgot_password/') .reply(200, { result: null }) return expect( client.forgotPasswordProvider('someemail'), ).to.eventually.equal('success') }) }) describe('.joinMeeting', () => { it('should return an object with shape { session, token, created } on success', () => { nock(baseURL) .get('/v1/appointment/meetingId123/join_meeting/') .reply(200, { result: { session: { session_id: 'session123', created: 'now', }, token: 'sessionToken123', created: 'right now', }, }) return client .setAccountType('provider') .joinMeeting('meetingId123') .then((result: any) => { expect(Object.keys(result)).to.include.members([ 'session', 'token', 'created', ]) }) }) it('should throw if called without a valid id parameter', () => { client.setAccountType('provider') return expect(client.joinMeeting(null)).to.eventually.be.rejectedWith( E.InvalidParametersError, /without an id/i, ) }) }) describe('.login', () => { it( 'should return a rejected promise of error type WrongAccountTypeError if the' + ' accountType passed in is not a valid option', () => { // }, ) it('should return a rejected TypeError error as a promise if the first argument is not a string', () => { // }) describe('patient', () => { describe('using credentials object', () => { it('Should return the response with user, members, token when logging in with credentials', () => { nock(baseURL) .post('/v1/account/patient/login/', { tv_uid: user.patient.tv_uid, tv_token: user.patient.tv_token, }) .reply(200, { result: { token, user: { user_id: 'userid23', document_symptoms_and_conditions: 'doc123', }, members: [{ user_id: 'memberuserid123' }], }, }) expect( client.login('patient', { tv_uid: user.patient.tv_uid, tv_token: user.patient.tv_token, }), ).to.eventually.have.all.keys('token', 'user', 'members') }) it('Should have set the token and default header when logging in with credentials (tv_uid + tv_token)', () => { nock(baseURL) .post('/v1/account/patient/login/', { tv_uid: user.patient.tv_uid, tv_token: user.patient.tv_token, }) .reply(200, { result: { token: 'token9000', user: {}, members: [] }, }) return client .login('patient', { tv_uid: user.patient.tv_uid, tv_token: user.patient.tv_token, }) .then(() => { const _token = client.getToken() const headers = client.getCurrentHeaders() expect(_token).to.equal('token9000') expect(headers).to.include({ Authorization: `JWT token9000` }) }) }) // TODO: find truevault client mock to make this work // it('Should have set the token and default header when logging in with credentials (username + password)', () => { // // Login through truevault first // nock(baseTvURL) // .post('/v1/auth/login/', { // username: user.patient.username, // password: user.patient.password, // }) // .reply(200, { // result: 'success', // transaction_id: 'id123', // user: { // access_token: user.patient.tv_token, // user_id: user.patient.user_id, // id: user.patient.tv_uid, // }, // }) // // Login with our backend after // nock(baseURL) // .post('/v1/account/patient/login/', { // tv_uid: user.patient.tv_uid, // tv_token: user.patient.tv_token, // }) // .reply(200, { result: { token, user: {}, members: [] } }) // return client // .login('patient', { // username: user.patient.username, // password: user.patient.password, // }) // .then(() => { // const token = client.getToken() // const headers = client.getCurrentHeaders() // expect(token).to.equal('token123') // expect(headers).to.include({ Authorization: `JWT token123` }) // }) // }) }) describe('using userId + token strings', () => { it('Should return the profile object when logging in with userId + token', () => { nock(baseURL) .get(`/v1/account/patient/userid123/`) .reply(200, { result: { user_id: user.patient.user_id, document_family_symptoms_and_conditions: 'doc123', }, }) expect( client.login('patient', user.patient.user_id, token), ).to.eventually.have.all.keys( 'user_id', 'document_family_symptoms_and_conditions', ) }) it('Should internally set the token', () => { nock(baseURL) .get(`/v1/account/patient/userid123/`) .reply(200, { result: { user_id: user.patient.user_id } }) return client .login('patient', user.patient.user_id, token) .then(() => expect(client.getToken()).to.equal('token123')) }) it('Should internally set the auth headers', () => { nock(baseURL) .get(`/v1/account/patient/userid123/`) .reply(200, { result: { user_id: user.patient.user_id } }) return client .login('patient', user.patient.user_id, token) .then(() => { const headers = client.getCurrentHeaders() expect(headers.Authorization).to.equal('JWT token123') }) }) }) }) describe('providers', () => { describe('using the userId + token strings', () => { it('Should internally set the token + headers when using user_id + tv_token strings', () => { nock(baseURL) .get(`/v1/account/provider/userid123/`) .reply(200, { result: { user_id: user.provider.user_id, email: 'bb123@gmail.com', NPI: '432432423', }, }) return client .login('provider', user.provider.user_id, token) .then(() => { const _token = client.getToken() const headers = client.getCurrentHeaders() expect(_token).to.equal('token123') expect(headers).to.include({ Authorization: 'JWT token123' }) }) }) it('Should return the profile object', () => { nock(baseURL) .get(`/v1/account/provider/userid123/`) .reply(200, { result: { user_id: user.provider.user_id, email: user.provider.email, NPI: '432432423', }, }) return client .login('provider', user.provider.user_id, token) .then((profile: types.Provider) => { expect(profile.user_id).to.equal('userid123') expect(profile.email).to.equal('bb123@gmail.com') expect(profile.NPI).to.equal('432432423') }) }) it('Should set the accountType on the store if credentials are valid', () => { nock(baseURL) .get(`/v1/account/provider/userid123/`) .reply(200, { result: { NPI: '432432423', }, }) return client .login('provider', user.provider.user_id, token) .then(() => { const accountType = client.getCurrentAccountType() expect(accountType).to.equal('provider') }) }) }) describe('using credentials object', () => { it('Should return the profile object', () => { nock(baseURL) .post('/v1/account/provider/login/', { email: user.provider.email, password: user.provider.password, }) .reply(200, { result: { token, provider: { user_id: user.provider.user_id, tv_uid: user.provider.tv_uid, }, }, }) expect( client.login('provider', { email: 'bb123@gmail.com', password: 'Breezep1@', }), ).to.eventually.include({ user_id: 'userid123', tv_uid: 'tv_uid123' }) }) it('Should have set the token and default headers', () => { nock(baseURL) .post('/v1/account/provider/login/', { email: user.provider.email, password: user.provider.password, }) .reply(200, { result: { token, provider: { user_id: user.provider.user_id, tv_uid: user.provider.tv_uid, tv_api_key: 'apk123', }, }, }) return client .login('provider', { email: 'bb123@gmail.com', password: 'Breezep1@', }) .then(() => { const _token = client.getToken() const headers = client.getCurrentHeaders() expect(_token).to.equal('token123') expect(headers).to.include({ Authorization: 'JWT token123' }) }) }) it('Should set the accountType on the store if success', () => { nock(baseURL) .post(`/v1/account/provider/login/`) .reply(200, { result: { token, provider: { user_id: user.provider.user_id, tv_api_key: 'apik123', }, }, }) return client .login('provider', { email: user.provider.email, password: user.provider.password, }) .then(() => { const accountType = client.getCurrentAccountType() expect(accountType).to.equal('provider') }) }) }) it('Should return the profile object when logging in with userId + token', () => { nock(baseURL) .get(`/v1/account/provider/userid123/`) .reply(200, { result: { user_id: user.provider.user_id, NPI: user.provider.NPI, }, }) return expect( client.login('provider', user.provider.user_id, token), ).to.eventually.include({ user_id: 'userid123', NPI: 'npi123' }) }) }) }) describe('.loginAsAdmin', () => { const url = '/v1/account/admin/login/' beforeEach(() => { nock(baseURL) .post(url) .reply(200, { result: { token: 'token123', }, }) }) it("should throw if email isn't provided", () => { return expect( client.login('admin', { email2: 'email123', password: 'pw123' }), ).to.eventually.be.rejectedWith(E.MissingParametersError) }) it("should throw if password isn't provided", () => { return expect( client.login('admin', { email: 'email123', fdsfsd: 'pw123' }), ).to.eventually.be.rejectedWith(E.MissingParametersError) }) it('should return the token if login is successful', () => { return expect( client.login('admin', { email: 'email123', password: 'pw123' }), ).to.eventually.equal('token123') }) }) describe('.queryAppointments', () => { it('Should fetch and return the results in the shape { pagination, ids, appointments }', () => { const url = '/v1/appointment/?status=1&status=2&patients=patient123&providers=provider123' nock(baseURL) .get(url) .reply(200, { result: { pagination: { object_count: 0, page_limit: 10, page_index: 1, num_pages: 1, }, data: [{ id: 'appointment1' }, { id: 'appointment2' }], }, }) client.setAccountType('patient') return client .queryAppointments({ patients: ['patient123'], providers: ['provider123'], status: [1, 2], }) .then((result: types.FetchAppointmentsReturnObject) => { expect(result.pagination).not.to.be.undefined expect(result.ids).not.to.be.undefined expect(result.appointments).not.to.be.undefined }) }) it('The optional filter param should be able to filter the results if used', () => { const url = '/v1/appointment/?status=1&status=2&patients=patient123&providers=provider123' nock(baseURL) .get(url) .reply(200, { result: { pagination: {}, data: [ { id: 'a1', is_walk_in: true }, { id: 'a2', is_walk_in: false }, { id: 'a3', is_walk_in: true }, { id: 'a4', is_walk_in: false }, { id: 'a5', is_walk_in: true }, { id: 'a6', is_walk_in: false }, ], }, }) const _filter = ( appt: types.Appointment, id: string, appointments: { [id: string]: types.Appointment }, ) => appt.is_walk_in !== false client.setAccountType('patient') return client .queryAppointments({ patients: ['patient123'], providers: ['provider123'], status: [1, 2], filter: _filter, }) .then(({ appointments }: { appointments: types.Appointments }) => { const ids = Object.keys(appointments) expect(ids).to.have.lengthOf(3) ids.forEach((id: any) => { expect(appointments[id].is_walk_in).to.be.true }) }) }) it( 'should reject if the parameters passed in are not any of: "patients", ' + '"providers", "status", "start_time", and "end_time"', () => { const params = { fruit: 'apple', color: 'red' } client.setAccountType('patient') return expect( client.queryAppointments(params), ).to.eventually.be.rejectedWith( E.InvalidParametersError, /None of the parameters are related to the search query/i, ) }, ) it('should reject if start_time or end_time is not a string', () => { const params = { start_time: 500, end_time: 'fdsfds', patients: 'fds', providers: 'fd', status: [1], } client.setAccountType('patient') return expect( client.queryAppointments(params), ).to.eventually.be.rejectedWith(TypeError, /needs to be a string/i) }) it('should return a rejected promise if the accountType using this is not a patient', () => { const params = { start_time: 500, end_time: 'fdsfds', patients: 'fds', providers: 'fd', status: [1], } client.setAccountType('provider') return expect( client.queryAppointments(params), ).to.eventually.be.rejectedWith( E.WrongAccountTypeError, /Only patients can use this URI/i, ) }) }) describe('.setAccountType', () => { it('should set the accountType on the store', () => { client.setAccountType('staffing_company') const current = client.getCurrentAccountType() expect(current).to.equal('staffing_company') const store = client.getStore() expect(store.accountType).to.equal('staffing_company') }) }) describe('.suspendProvider', () => { beforeEach(() => { nock(baseURL) .get('/v1/account/provider/provider123/suspend/') .reply(200, { result: { user_id: 'provider123', is_approved: false }, }) }) it('should throw if the userId parameter is undefined', () => { client.setAccountType('admin') return expect(client.suspendProvider()).to.eventually.be.rejectedWith( E.MissingParametersError, ) }) it('should return the updated profile object with is_approved equal to false if success', () => { client.setAccountType('admin') return expect( client.suspendProvider('provider123'), ).to.eventually.include({ is_approved: false, }) }) }) describe('.updateAppointment', () => { it('should throw if none of the valid keys to update are passed in', () => { const updates = { apple: 'pie', email: 'bb123@gmail.com ' } client.setAccountType('provider') return expect( client.updateAppointment('appointment123', updates), ).to.eventually.be.rejectedWith( E.InvalidKeysError, /cannot update appointment/i, ) }) it('should return the updated appointment object if the call was successful', () => { const id = 'appointment123' const updates = { purpose: 'knee pain', document_present_history_illness: 'hpi-id123', } nock(baseURL) .put(`/v1/appointment/${id}/`) .reply(205, { result: { id, patient: {}, provider: {}, status: 2, }, }) return client .setAccountType('provider') .updateAppointment(id, updates) .then((result: any) => { expect(result.id).to.not.be.undefined expect(result.patient).to.not.be.undefined expect(result.provider).to.not.be.undefined expect(result.status).to.not.be.undefined }) }) }) describe('.updateAppointmentReview', () => { const args = { appointment: 'hi', rating: 5, comment: 'hello' } const url = '/v1/appointment_review/hi/' it('should return a rejected promise if none of the param keys are valid', () => { const params = { apple: 'red', green: 'what' } client.setAccountType('patient') return expect( client.updateAppointmentReview(params), ).to.eventually.be.rejectedWith( E.InvalidParametersError, /parameters: appointment, rating, comment/i, ) }) it('should return the updated appointment review object if the call was successful', () => { nock(baseURL) .put(url) .reply(205, { result: { ...args, rating: 5 } }) client.setAccountType('patient') return expect(client.updateAppointmentReview(args)).to.eventually.include( args, ) }) it('should throw with a WrongAccountType error if the accountType is not a patient', () => { client.setAccountType('marketer') return expect( client.updateAppointmentReview(args), ).to.eventually.be.rejectedWith(E.WrongAccountTypeError, /Only patients/i) }) }) describe('.updatePatientDocument', () => { const vaultId = '79c8079b-250c-444d-bd52-2f46855db234' const docId = '01770eba-db2b-4c31-bc14-8b87cb8914d5' const ownerId = 'owner123' const tvUrl = `/v1/vaults/${vaultId}/documents/${docId}?_tv_sdk=1.3.0` const changes = { document: { hello: 'bro' } } beforeEach(() => { nock(baseTvURL) .put(tvUrl, changes) .reply(200, { document: { id: docId, vault_id: vaultId } }) client.setAccountType('patient') }) it('should throw if docId is not a valid string', () => { return expect( client.updatePatientDocument(null, changes), ).to.eventually.be.rejectedWith( E.InvalidParametersError, /document id is invalid/i, ) }) it('should throw if the changes parameter is not an object', () => { return expect( client.updatePatientDocument(docId, 'fdsfds'), ).to.eventually.be.rejectedWith( TypeError, /"changes" parameter is not an object or array/i, ) }) it('should return an object with the shape { id, ownerId } if the call was successful', () => { client.tvClient = { updateDocument: () => ({ id: docId, owner_id: ownerId }), } return expect( client.updatePatientDocument(docId, changes), ).to.eventually.include({ id: docId, ownerId }) }) }) describe('.updateBackendPatient', () => { const userId = 'myid123' const changes = { languages: {}, profile: { document_procedures_and_treatments: 'ff', }, } beforeEach(() => { nock(baseURL) .put(`/v1/account/patient/${userId}/`, changes) .reply(200, { result: { languages: { 'en-US': true }, document_procedures_and_treatments: 'ff', }, }) client.setAccountType('admin') }) it('should return the patient object on success', () => { return expect( client.updateBackendPatient(userId, changes), ).to.eventually.include({ document_procedures_and_treatments: 'ff', }) }) it('should throw if userId is undefined', () => { return expect( client.updateBackendPatient(undefined, changes), ).to.eventually.be.rejectedWith(E.MissingParametersError) }) it('should throw if options.languages is not an object and it was provided', () => { return expect( client.updateBackendPatient(userId, { ...changes, languages: ['en-US'], }), ).to.eventually.be.rejectedWith(TypeError) }) it('should throw if changes.profile was provided and it is not an object', () => { return expect( client.updateBackendPatient(userId, { ...changes, profile: [] }), ).to.eventually.be.rejectedWith(TypeError) }) }) describe('.updateProvider', () => { const userId = 'myid123' const changes = { first_name: 'Henry', gender: 'MALE' } beforeEach(() => { nock(baseURL) .put(`/v1/account/provider/${userId}/`, changes) .reply(205, { data: { first_name: 'Henry', gender: 'MALE', city: 'South Park', NPI: 'npi123', }, }) client.setAccountType('admin') }) it('should return the provider object on success', () => { return expect( client.updateProvider(userId, changes), ).to.eventually.include({ first_name: 'Henry', gender: 'MALE', }) }) it('should throw if userId is undefined', () => { return expect( client.updateProvider(undefined, changes), ).to.eventually.be.rejectedWith(E.MissingParametersError) }) it('should throw if options.languages is not an object and it was provided', () => { return expect( client.updateProvider(userId, { ...changes, languages: ['en-US'], }), ).to.eventually.be.rejectedWith(TypeError) }) it('should throw if options.specialties is not a string or array if provided', () => { return expect( client.updateProvider(userId, { ...changes, specialties: { FAMILY_MEDICINE: true }, }), ).to.eventually.be.rejectedWith(TypeError) }) }) describe('._constructURL', () => { it('should return the url, correctly appending the params', () => { const obj = { one: 'number', fruit: 'apples', red: 'hot', maybe: ['yes', 'or', 'no'], } const url = client._constructURL( 'https://testapi.aitmed.com/v1/appointment?', obj, ) expect(url).to.equal( 'https://testapi.aitmed.com/v1/appointment?one=number&fruit=apples&red=hot&maybe=yes,or,no', ) }) }) describe('._toClonedQueries', () => { it('should transform an array to cloned queries used for some backend api calls', () => { let uri = client._toClonedQueries('status', [1, 2]) expect(uri).to.equal('1&status=2') uri = client._toClonedQueries('providers', ['prov1', 'abc']) expect(uri).to.equal('prov1&providers=abc') }) }) })