def test_preflight_valid(self): # setup pre-flight conditions expected to pass ds_p3p = INTERVENTION.decision_support_p3p ds_client = Client(client_id='12345', client_secret='54321', user_id=TEST_USER_ID, intervention=ds_p3p, _redirect_uris='http://testsite.org', callback_url='http://callback.one') service = self.add_service_user(sponsor=self.test_user) with SessionScope(db): db.session.add(ds_client) db.session.commit() ds_client = db.session.merge(ds_client) service = db.session.merge(service) create_service_token(client=ds_client, user=service) # Export sp = SitePersistence(target_dir=self.tmpdir) sp.export(staging_exclusion=True) assert Token.query.count() == 1 # Delete service account, expect it to return with SessionScope(db): db.session.delete(service) db.session.commit() assert User.query.count() == 1 assert Token.query.count() == 0 # Import sp.import_(keep_unmentioned=True, staging_exclusion=True) assert Token.query.count() == 1 assert User.query.count() == 2
def test_unique(self): """Try adding a non-unique identifier, expect exception""" constrained = Identifier( system='http://us.truenth.org/identity-codes/external-study-id', value='unique-one') with SessionScope(db): db.session.add(constrained) second_user = self.add_user('second') constrained = db.session.merge(constrained) second_user.add_identifier(constrained) user = db.session.merge(self.test_user) with pytest.raises(Conflict): user.add_identifier(constrained)
def shallow_org_tree(self): """Create shallow org tree for common test needs""" org_101 = Organization(id=101, name='101') org_102 = Organization(id=102, name='102') org_1001 = Organization(id=1001, name='1001', partOf_id=101) already_done = Organization.query.get(101) if already_done: return with SessionScope(db): [db.session.add(org) for org in (org_101, org_102, org_1001)] db.session.commit() OrgTree.invalidate_cache()
def test_ill_formed_ident_search(self): ident = Identifier(system='http://example.com', value='testy') ui = UserIdentifier(identifier=ident, user_id=TEST_USER_ID) with SessionScope(db): db.session.add(ident) db.session.add(ui) db.session.commit() self.promote_user(role_name=ROLE.PATIENT) self.login() ident = db.session.merge(ident) rv = self.client.get( '/api/patient?identifier=system"http://example.com",value="testy"', follow_redirects=True) self.assert400(rv)
def test_group_list(self): grp1 = Group(name='test_1') grp2 = Group(name='test_2') with SessionScope(db): db.session.add(grp1) db.session.add(grp2) db.session.commit() # use api to obtain list self.login() rv = self.client.get('/api/group/') self.assert200(rv) bundle = rv.json self.assertEquals(len(bundle['groups']), 2)
def create_fake_relationships(self): other_user = self.add_user(username='******') partner = Relationship.query.filter_by(name='partner').first() rel = UserRelationship(user_id=TEST_USER_ID, relationship_id=partner.id, other_user_id=other_user.id) sponsor = Relationship.query.filter_by(name='sponsor').first() rel2 = UserRelationship(user_id=other_user.id, relationship_id=sponsor.id, other_user_id=TEST_USER_ID) with SessionScope(db): db.session.add(rel) db.session.add(rel2) db.session.commit()
def test_get(self): audit = Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID) tou = ToU(audit=audit, agreement_url=tou_url, type='website terms of use') with SessionScope(db): db.session.add(tou) db.session.commit() self.login() rv = self.client.get('/api/user/{}/tou'.format(TEST_USER_ID)) doc = json.loads(rv.data) self.assert200(rv) self.assertEquals(len(doc['tous']), 1)
def test_get(self): audit = Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID) tou = ToU(audit=audit, agreement_url=tou_url, type='website terms of use') with SessionScope(db): db.session.add(tou) db.session.commit() self.login() response = self.client.get('/api/user/{}/tou'.format(TEST_USER_ID)) doc = response.json assert response.status_code == 200 assert len(doc['tous']) == 1
def test_ident_search(self): ident = Identifier(system='http://example.com', value='testy') ui = UserIdentifier(identifier=ident, user_id=TEST_USER_ID) with SessionScope(db): db.session.add(ident) db.session.add(ui) db.session.commit() self.promote_user(role_name=ROLE.PATIENT.value) self.login() ident = db.session.merge(ident) response = self.client.get('/api/patient?identifier={}'.format( json.dumps(ident.as_fhir())), follow_redirects=True) assert response.status_code == 200
def test_group_list(self): grp1 = Group(name='test_1') grp2 = Group(name='test_2') with SessionScope(db): db.session.add(grp1) db.session.add(grp2) db.session.commit() # use api to obtain list self.login() response = self.client.get('/api/group/') assert response.status_code == 200 bundle = response.json assert len(bundle['groups']) == 2
def test_organization_search(self): self.shallow_org_tree() count = Organization.query.count() assert count > 1 # add region to one org, we should get only that one back region = Identifier(value='state:NY', system=PRACTICE_REGION) with SessionScope(db): db.session.add(region) db.session.commit() region = db.session.merge(region) oi = OrganizationIdentifier(organization_id=1001, identifier_id=region.id) with SessionScope(db): db.session.add(oi) db.session.commit() # use api to obtain FHIR bundle self.login() response = self.client.get('/api/organization?state=NY') assert response.status_code == 200 bundle = response.json assert bundle['resourceType'] == 'Bundle' assert len(bundle['entry']) == 1
def test_unique_deleted(self): """Try adding a non-unique identifier from deleted user""" constrained = Identifier( system='http://us.truenth.org/identity-codes/external-study-id', value='unique-one') with SessionScope(db): db.session.add(constrained) second_user = self.add_user('second') constrained = db.session.merge(constrained) second_user.add_identifier(constrained) second_user.delete_user(acting_user=self.test_user) user = db.session.merge(self.test_user) user.add_identifier(constrained) assert constrained in user.identifiers
def test_delete_unnamed(self): keeper = AppText(name='keep me', custom_text='worthy') mp = ModelPersistence( AppText, lookup_field='name', sequence_name='apptext_id_seq', target_dir=self.tmpdir) with SessionScope(db): db.session.add(keeper) db.session.commit() mp.export() # Add another app text, expecting it'll be removed bogus = AppText(name='temp', custom_text='not worthy') with SessionScope(db): db.session.add(bogus) db.session.commit() # Import w/ keep_unmentioned and expect both mp.import_(keep_unmentioned=True) assert AppText.query.count() == 2 # Now import, and expect only keeper to remain mp.import_(keep_unmentioned=False) assert AppText.query.count() == 1 assert AppText.query.first().name == 'keep me'
def test_lookup_for_user(self): crv = Organization(name='CRV') epic26 = Questionnaire(name='epic26') eproms_add = Questionnaire(name='eproms_add') comorb = Questionnaire(name='comorb') with SessionScope(db): db.session.add(crv) db.session.add(epic26) db.session.add(eproms_add) db.session.add(comorb) db.session.commit() crv, epic26, eproms_add, comorb = map( db.session.merge, (crv, epic26, eproms_add, comorb)) bank = QuestionnaireBank(name='CRV', organization_id=crv.id) for rank, q in enumerate((epic26, eproms_add, comorb)): qbq = QuestionnaireBankQuestionnaire(questionnaire_id=q.id, days_till_due=7, days_till_overdue=90, rank=rank) bank.questionnaires.append(qbq) self.test_user.organizations.append(crv) with SessionScope(db): db.session.add(bank) db.session.commit() # User associated with CRV org should generate appropriate # questionnaires self.test_user = db.session.merge(self.test_user) qd = QuestionnaireDetails(self.test_user, datetime.utcnow()) results = list(qd.baseline()) self.assertEquals(3, len(results)) # confirm rank sticks self.assertEquals(results[0]['name'], 'epic26') self.assertEquals(results[2]['name'], 'comorb')
def setup_org_n_rp(org=None, org_name='org', rp_name='proto', retired_as_of=None): """Create simple test org with RP, return (org, rp, rp_id)""" if not org: org = Organization(name=org_name) rp = ResearchProtocol(name=rp_name) with SessionScope(db): db.session.add(org) db.session.add(rp) db.session.commit() org, rp = map(db.session.merge, (org, rp)) if not retired_as_of: org.research_protocols.append(rp) else: o_rp = OrganizationResearchProtocol(research_protocol=rp, organization=org, retired_as_of=retired_as_of) with SessionScope(db): db.session.add(o_rp) db.session.commit() org, rp = map(db.session.merge, (org, rp)) return (org, rp, rp.id)
def test_multiple_rps_in_fhir(self): yesterday = datetime.utcnow() - timedelta(days=1) lastyear = datetime.utcnow() - timedelta(days=365) org = Organization(name='Testy') rp1 = ResearchProtocol(name='rp1') rp2 = ResearchProtocol(name='yesterday') rp3 = ResearchProtocol(name='last year') with SessionScope(db): map(db.session.add, (org, rp1, rp2, rp3)) db.session.commit() org, rp1, rp2, rp3 = map(db.session.merge, (org, rp1, rp2, rp3)) o_rp1 = OrganizationResearchProtocol(research_protocol=rp1, organization=org) o_rp2 = OrganizationResearchProtocol(research_protocol=rp2, organization=org, retired_as_of=yesterday) o_rp3 = OrganizationResearchProtocol(research_protocol=rp3, organization=org, retired_as_of=lastyear) with SessionScope(db): map(db.session.add, (o_rp1, o_rp2, o_rp3)) db.session.commit() org, rp1, rp2, rp3 = map(db.session.merge, (org, rp1, rp2, rp3)) data = org.as_fhir() assert org.name == data['name'] rps = [ extension for extension in data['extension'] if extension['url'] == ResearchProtocolExtension.extension_url ] assert len(rps) == 1 assert len(rps[0]['research_protocols']) == 3 # confirm the order is descending in the custom accessor method results = [(rp, retired) for rp, retired in org.rps_w_retired()] assert [(rp1, None), (rp2, yesterday), (rp3, lastyear)] == results
def test_organization_search(self): self.shallow_org_tree() count = Organization.query.count() self.assertTrue(count > 1) # add region to one org, we should get only that one back region = Identifier(value='state:NY', system=PRACTICE_REGION) with SessionScope(db): db.session.add(region) db.session.commit() region = db.session.merge(region) oi = OrganizationIdentifier(organization_id=1001, identifier_id=region.id) with SessionScope(db): db.session.add(oi) db.session.commit() # use api to obtain FHIR bundle self.login() rv = self.client.get('/api/organization?state=NY') self.assert200(rv) bundle = rv.json self.assertTrue(bundle['resourceType'], 'Bundle') self.assertEquals(len(bundle['entry']), 1)
def add_service_user(self, sponsor=None): """create and return a service user for sponsor Assign any user to sponsor to use a sponsor other than the default test_user """ if not sponsor: sponsor = self.test_user if sponsor not in db.session: sponsor = db.session.merge(sponsor) service_user = sponsor.add_service_account() with SessionScope(db): db.session.add(service_user) db.session.commit() return db.session.merge(service_user)
def test_ident_nomatch_search(self): ident = Identifier(system='http://example.com', value='testy') ui = UserIdentifier(identifier=ident, user_id=TEST_USER_ID) with SessionScope(db): db.session.add(ident) db.session.add(ui) db.session.commit() self.promote_user(role_name=ROLE.PATIENT) self.login() ident = db.session.merge(ident) # modify the system to mis match id_str = json.dumps(ident.as_fhir()).replace("example.com", "wrong-system.com") rv = self.client.get('/api/patient?identifier={}'.format(id_str), follow_redirects=True) self.assert404(rv)
def test_org_rp_reference(self): rp = ResearchProtocol(name="test_rp") with SessionScope(db): db.session.add(rp) db.session.commit() rp = db.session.merge(rp) org_data = {"name": "test_org", "extension": [ {"url": TRUENTH_RP_EXTENSION, "research_protocols": [{'name': "test_rp"}]} ]} org = Organization.from_fhir(org_data) self.assertEqual(1, len(org.research_protocols)) self.assertEqual(org.research_protocols[0].id, rp.id)
def test_SR_timeout(self): # SR users get 1 hour ui = UserIntervention(user_id=TEST_USER_ID, intervention_id=INTERVENTION.SEXUAL_RECOVERY.id) with SessionScope(db): db.session.add(ui) db.session.commit() self.login() response = self.client.get('/next-after-login', follow_redirects=False) cookies = SimpleCookie() [ cookies.load(item[1]) for item in response.headers if item[0] == 'Set-Cookie' ] assert int(cookies['SS_INACTIVITY_TIMEOUT'].value) == 60 * 60
def test_service_account_promotion(self): """Confirm we can not promote a service account """ self.add_client() test_user = User.query.get(TEST_USER_ID) service_user = test_user.add_service_account() with SessionScope(db): db.session.add(service_user) db.session.commit() service_user = db.session.merge(service_user) # try to promote - which should fail assert pytest.raises(RoleError, add_role, service_user, ROLE.APPLICATION_DEVELOPER.value) assert len(service_user.roles) == 1
def test_australian_indigenous_status(self): """Apply a few indigenous via FHIR from the NHHD_291036 value set""" # Add two indigenous directly - one in and one not in extension below concepts = Coding.query.filter( and_(Coding.code.in_(('1', '4')), Coding.system == TRUENTH_VALUESET_NHHD_291036)).all() with SessionScope(db): db.session.add(UserIndigenous(user_id=TEST_USER_ID, coding_id=concepts[0].id)) db.session.add(UserIndigenous(user_id=TEST_USER_ID, coding_id=concepts[1].id)) db.session.commit() self.test_user = db.session.merge(self.test_user) self.assertEquals(2, self.test_user.indigenous.count()) extension = {"url": TRUENTH_EXTENSTION_NHHD_291036} kls = user_extension_map(user=self.test_user, extension=extension) self.assertTrue(isinstance(kls, UserIndigenousStatusExtension)) # generate FHIR from user's ethnicities fhir_data = kls.as_fhir() self.assertEquals(2, len(fhir_data['valueCodeableConcept']['coding'])) codes = [c['code'] for c in fhir_data['valueCodeableConcept']['coding']] self.assertIn('1', codes) self.assertIn('4', codes) # now create a new extension (FHIR like) and apply to the user extension = {"url": TRUENTH_EXTENSTION_NHHD_291036, "valueCodeableConcept": { "coding": [ {"system": TRUENTH_VALUESET_NHHD_291036, "code": "1" }, {"system": TRUENTH_VALUESET_NHHD_291036, "code": "9" }, ] }} ue = UserIndigenousStatusExtension(self.test_user, extension) ue.apply_fhir() self.assertEquals(2, self.test_user.indigenous.count()) found = [c.code for c in self.test_user.indigenous] self.assertIn('1', found) self.assertIn('9', found)
def test_job_delete(self): self.promote_user(role_name=ROLE.ADMIN.value) self.login() job = ScheduledJob(name="test_del", task="test", schedule="0 0 * * *") with SessionScope(db): db.session.add(job) db.session.commit() job = db.session.merge(job) job_id = job.id resp = self.client.delete('/api/scheduled_job/{}'.format(job_id)) self.assert200(resp) self.assertFalse(ScheduledJob.query.all()) resp = self.client.delete('/api/scheduled_job/999') self.assert404(resp)
def test_get_by_type(self): timestamp = datetime.utcnow() audit = Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID, timestamp=timestamp) tou = ToU(audit=audit, agreement_url=tou_url, type='privacy policy') with SessionScope(db): db.session.add(tou) db.session.commit() self.login() rv = self.client.get( '/api/user/{}/tou/privacy-policy'.format(TEST_USER_ID)) self.assert200(rv) self.assertEquals(rv.json['accepted'], timestamp.strftime("%Y-%m-%dT%H:%M:%S")) self.assertEquals(rv.json['type'], 'privacy policy')
def add_user( self, username, first_name="", last_name="", image_url=None, pre_registered=False): """Create a user and add to test db, and return it""" # Unless testing a pre_registered case, give the user a fake password # so they appear registered password = None if pre_registered else 'fakePa$$' test_user = User( username=username, first_name=first_name, last_name=last_name, image_url=image_url, password=password) with SessionScope(db): db.session.add(test_user) db.session.commit() test_user = db.session.merge(test_user) # Avoid testing cached/stale data invalidate_assessment_status_cache(test_user.id) return test_user
def test_no_email(self): # User w/o email shouldn't trigger communication mock_communication_request('localized', '{"days": 14}') # Fake a user associated with localized org # and mark all baseline questionnaires as in-progress self.bless_with_basics(backdate=relativedelta(days=22), local_metastatic='localized') self.test_user = db.session.merge(self.test_user) self.test_user.email = NO_EMAIL_PREFIX with SessionScope(db): db.session.commit() update_patient_loop(update_cache=False, queue_messages=True) expected = Communication.query assert expected.count() == 0
def test_redirect_validation(self): self.promote_user(role_name=ROLE.ADMIN.value) self.promote_user(role_name=ROLE.STAFF.value) org = Organization(name='test org') user = get_user(TEST_USER_ID) with SessionScope(db): db.session.add(org) user.organizations.append(org) db.session.commit() self.login() client = self.add_client() client_url = client._redirect_uris local_url = "http://{}/home?test".format(self.app.config.get('SERVER_NAME')) invalid_url = 'http://invalid.org' # validate redirect of /website-consent-script GET rv = self.client.get('/website-consent-script/{}?redirect_url=' '{}'.format(TEST_USER_ID, local_url)) self.assert200(rv) rv2 = self.client.get('/website-consent-script/{}?redirect_url=' '{}'.format(TEST_USER_ID, invalid_url)) self.assert401(rv2) # validate redirect of /login/<provider> GET rv3 = self.client.get('/login/TESTING?user_id={}&next=' '{}'.format(TEST_USER_ID, client_url), follow_redirects=True) self.assert200(rv3) rv4 = self.client.get('/login/TESTING?user_id={}&next=' '{}'.format(TEST_USER_ID, invalid_url), follow_redirects=True) self.assert401(rv4) # validate redirect of /challenge POST formdata = {'user_id': TEST_USER_ID, 'next_url': local_url} rv5 = self.client.post('/challenge', data=formdata) self.assert200(rv5) formdata['next_url'] = invalid_url rv6 = self.client.post('/challenge', data=formdata) self.assert401(rv6)
def test_job_get(self): self.promote_user(role_name=ROLE.ADMIN.value) self.login() job = ScheduledJob(name="test_get", task="test", schedule="0 0 * * *") with SessionScope(db): db.session.add(job) db.session.commit() job = db.session.merge(job) job_id = job.id resp = self.client.get('/api/scheduled_job/{}'.format(job_id)) self.assert200(resp) self.assertEqual(resp.json['task'], 'test') resp = self.client.get('/api/scheduled_job/999') self.assert404(resp)
def test_completed_older_rp(self): """If current qb completed on older rp, should show as done""" fourmonthsago = now - timedelta(days=120) weekago = now - timedelta(weeks=1) twoweeksago = now - timedelta(weeks=2) org = self.setup_org_qbs(rp_name='v2', retired_as_of=weekago) org_id = org.id self.setup_org_qbs(org=org, rp_name='v3') self.promote_user(role_name=ROLE.PATIENT.value) self.test_user = db.session.merge(self.test_user) self.test_user.organizations.append(org) audit = Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID) uc = UserConsent(user_id=TEST_USER_ID, organization_id=org_id, audit=audit, agreement_url='http://no.com', acceptance_date=fourmonthsago) with SessionScope(db): db.session.add(audit) db.session.add(uc) db.session.commit() user = db.session.merge(self.test_user) # Now, should still be rp v3, 3mo recurrence a_s = QB_Status(user=user, as_of_date=now) assert (a_s.current_qbd().questionnaire_bank.name == 'CRV_recurring_3mo_period v3') assert a_s.instruments_needing_full_assessment() == [ 'epic26_v3', 'eortc_v3' ] # Complete the questionnaire from the 3mo v2 QB v2qb = QuestionnaireBank.query.filter( QuestionnaireBank.name == 'CRV_recurring_3mo_period v2').one() mock_qr('epic26_v2', timestamp=twoweeksago, qb=v2qb, iteration=0) mock_qr('eortc_v2', timestamp=twoweeksago, qb=v2qb, iteration=0) # Two weeks ago, should be completed user = db.session.merge(user) a_s = QB_Status(user=user, as_of_date=twoweeksago) assert a_s.overall_status == OverallStatus.completed # Current should also be completed, even tho protocol changed a_s = QB_Status(user=user, as_of_date=now) assert a_s.overall_status == OverallStatus.completed