class TestTargets(unittest.TestCase): mock_data = mock_data = ( '12827,Volunteer Recruitment Tiers,Tier,109957740\n' '12827,Volunteer Recruitment Tiers,Tier,109957754') mock_result = Table([ ('12827', 'Volunteer Recruitment Tiers', 'Tier', '109957740'), ('12827', 'Volunteer Recruitment Tiers', 'Tier', '109957754')]) def setUp(self): self.van = VAN(os.environ['VAN_API_KEY'], db="MyVoters", raise_for_status=False) def tearDown(self): pass @requests_mock.Mocker() def test_get_targets(self, m): # Create response json = {u'count': 2, u'items': [{u'targetId': 12827, u'type': u'TEST CODE', u'name': u'TEST CODE', u'description': None, u'points': 20, u'areSubgroupsSticky': False, u'status': u'Active', u'subgroups': None, u'markedSubgroup': None}], u'nextPageLink': None} m.get(self.van.connection.uri + 'targets', json=json) # Expected Structure expected = ['targetId', 'type', 'name', 'description', 'points', 'areSubgroupsSticky', 'status', 'subgroups', 'markedSubgroup'] # Assert response is expected structure self.assertTrue(validate_list(expected, self.van.get_targets())) # To Do: Test what happens when it doesn't find any targets @requests_mock.Mocker() def test_get_target(self, m): # Create response json = {u'targetId': 15723, u'name': u'Mail_VR_Chase', u'type': u'Dynamic', u'description': None, u'points': 15, u'areSubgroupsSticky': False, u'status': u'Active', u'subgroups': [{u'targetId': 12827, u'fullName': u'April_VR_Chase Calls', u'name': u'April_Chase_20', u'subgroupId': 46803, u'isAssociatedWithBadges': True}], u'markedSubgroup': None} m.get(self.van.connection.uri + 'targets/15723', json=json) self.assertEqual(json, self.van.get_target(15723)) @requests_mock.Mocker() def test_create_target_export(self, m): export_job_id = '{"exportJobId": "455961790"}' target_id = 12827 m.post(self.van.connection.uri + 'targetExportJobs', json=export_job_id, status_code=204) # Test that it doesn't throw and error r = self.van.create_target_export(target_id, webhook_url=None) self.assertEqual(r, export_job_id) @requests_mock.Mocker() def test_get_target_export(self, m): export_job_id = 455961790 json = [{ "targetId": 12827, "file": { "downloadUrl": ( "https://ngpvan.blob.core.windows.net/" "target-export-files/TargetExport_455961790.csv"), "dateExpired": "null", "recordCount": 1016883}, "webhookUrl": "null", "exportJobId": 455961790, "jobStatus": "Complete"}] download_url = ( 'https://ngpvan.blob.core.windows.net/target-export-files/TargetExport_455961790.csv') m.post(self.van.connection.uri + 'targetExportJobs', json=export_job_id, status_code=204) m.get(self.van.connection.uri + 'targetExportJobs/455961790', json=json) m.get(download_url, text=self.mock_data) assert_matching_tables(self.van.get_target_export(export_job_id), self.mock_result)
# ### CODE import os # noqa: E402 import random # noqa: E402 from parsons import VAN # noqa: E402 from parsons import logger # noqa: E402 # Setup # If variables specified above, sets them as environmental variables for name, value in config_vars.items(): if value.strip() != "": os.environ[name] = value van = VAN(db=os.environ["VAN_DB_NAME"]) # Get details on the saved list we're pulling from and the folder we're uploading to saved_list = van.get_saved_list(os.environ["VAN_SAVED_LIST_ID"]) folder = van.get_folder(os.environ["VAN_FOLDER_ID"]) # If you're receiving errors when trying to call this method related to permissions, you may want to # reach out to [email protected] to make sure your API key has the correct permissions. saved_list_download = van.download_saved_list(os.environ["VAN_SAVED_LIST_ID"]) # Generate a random sample of VAN IDs from the list saved_list_sample_ids = random.sample( saved_list_download["VanID"], int(os.environ["VAN_SAMPLE_LIST_SIZE"]), )
class TestActivistCodes(unittest.TestCase): def setUp(self): self.van = VAN(os.environ['VAN_API_KEY'], db="MyVoters", raise_for_status=False) def tearDown(self): pass @requests_mock.Mocker() def test_get_activist_codes(self, m): # Create response json = { u'count': 43, u'items': [{ u'status': u'Active', u'scriptQuestion': None, u'name': u'TEST CODE', u'mediumName': u'TEST CODE', u'activistCodeId': 4388538, u'shortName': u'TC', u'type': u'Action', u'description': None }], u'nextPageLink': None } m.get(self.van.connection.uri + 'activistCodes', json=json) # Expected Structure expected = [ 'status', 'scriptQuestion', 'name', 'mediumName', 'activistCodeId', 'shortName', 'type', 'description' ] # Assert response is expected structure self.assertTrue(validate_list(expected, self.van.get_activist_codes())) # To Do: Test what happens when it doesn't find any ACs @requests_mock.Mocker() def test_get_activist_code(self, m): # Create response json = { "status": "Active", "scriptQuestion": "null", "name": "Anti-Choice", "mediumName": "Anti", "activistCodeId": 4135099, "shortName": "AC", "type": "Constituency", "description": "A person who has been flagged as anti-choice." } m.get(self.van.connection.uri + 'activistCodes/4388538', json=json) self.assertEqual(json, self.van.get_activist_code(4388538)) @requests_mock.Mocker() def test_toggle_activist_code(self, m): # Test apply activist code m.post(self.van.connection.uri + 'people/2335282/canvassResponses', status_code=204) self.assertTrue( self.van.toggle_activist_code(2335282, 4429154, 'apply'), 204) # Test remove activist code m.post(self.van.connection.uri + 'people/2335282/canvassResponses', status_code=204) self.assertTrue( self.van.toggle_activist_code(2335282, 4429154, 'remove'), 204) @requests_mock.Mocker() def test_apply_activist_code(self, m): # Test apply activist code m.post(self.van.connection.uri + 'people/2335282/canvassResponses', status_code=204) self.assertEqual(self.van.apply_activist_code(2335282, 4429154), 204) @requests_mock.Mocker() def test_remove_activist_code(self, m): # Test remove activist code m.post(self.van.connection.uri + 'people/2335282/canvassResponses', status_code=204) self.assertEqual(self.van.remove_activist_code(2335282, 4429154), 204)
class TestSavedLists(unittest.TestCase): def setUp(self): self.van = VAN(os.environ['VAN_API_KEY'], db="MyVoters", raise_for_status=False) def tearDown(self): pass @requests_mock.Mocker() def test_get_saved_lists(self, m): json = {'count': 1, 'items': [ {"savedListId": 517612, "listCount": 974656, "name": "LikelyParents(16andunder)_DWID_S... - MN", "doorCount": 520709, "description": "null" } ], 'nextPageLink': None} m.get(self.van.connection.uri + 'savedLists', json=json) expected = ['savedListId', 'listCount', 'name', 'doorCount', 'description'] self.assertTrue(validate_list(expected, self.van.get_saved_lists())) @requests_mock.Mocker() def test_get_saved_list(self, m): saved_list_id = 517612 json = {"savedListId": 517612, "listCount": 974656, "name": "LikelyParents(16andunder)_DWID_S... - MN", "doorCount": 520709, "description": "null" } m.get(self.van.connection.uri + f'savedLists/{saved_list_id}', json=json) # expected = ['savedListId', 'listCount', 'name', 'doorCount', 'description'] self.assertEqual(self.van.get_saved_list(saved_list_id), json) def test_upload_saved_list(self): cloud_storage.post_file = mock.MagicMock() cloud_storage.post_file.return_value = 'https://box.com/my_file.zip' self.van.connection._soap_client = mock.MagicMock() self.van.get_folders = mock.MagicMock() self.van.get_folders.return_value = [{'folderId': 1}] tbl = Table([['VANID'], ['1'], ['2'], ['3']]) self.van.upload_saved_list( tbl, 'GOTV List', 1, replace=True, url_type='S3', bucket='tmc-scratch') assert self.van.connection._soap_client.service.CreateAndStoreSavedList.called @requests_mock.Mocker() def test_upload_saved_list_rest(self): cloud_storage.post_file = mock.MagicMock() cloud_storage.post_file.return_value = 'https://box.com/my_file.zip' self.van.get_folders = mock.MagicMock() self.van.get_folders.return_value = [{'folderId': 1}] tbl = Table([['VANID'], ['1'], ['2'], ['3']]) response = self.van.upload_saved_list_rest( tbl=tbl, url_type="S3", folder_id=1, list_name="GOTV List", description="parsons test list", callback_url="https://webhook.site/69ab58c3-a3a7-4ed8-828c-1ea850cb4160", columns=["VANID"], id_column="VANID", bucket="tmc-scratch", overwrite=517612 ) self.assertIn("jobId", response) @requests_mock.Mocker() def test_get_folders(self, m): json = {u'count': 2, u'items': [ { u'folderId': 5046, u'name': u'#2018_MN_active_universe' }, {u'folderId': 2168, u'name': u'API Generated Lists' } ], u'nextPageLink': None} m.get(self.van.connection.uri + 'folders', json=json) expected = ['folderId', 'name'] self.assertTrue(validate_list(expected, self.van.get_folders())) @requests_mock.Mocker() def test_get_folder(self, m): folder_id = 5046 json = {"folderId": 5046, "name": "#2018_MN_active_universe"} m.get(self.van.connection.uri + f'folders/{folder_id}', json=json) self.assertEqual(json, self.van.get_folder(folder_id)) @requests_mock.Mocker() def test_export_job_types(self, m): json = {u'count': 1, u'items': [{u'exportJobTypeId': 4, u'name': u'SavedListExport'}], u'nextPageLink': None} m.get(self.van.connection.uri + 'exportJobTypes', json=json) expected = ['exportJobTypeId', 'name'] self.assertTrue(validate_list(expected, self.van.get_export_job_types())) @requests_mock.Mocker() def test_export_job_create(self, m): saved_list_id = 517612 json = {"status": "Completed", "errorCode": "null", "exportJobGuid": "bf4d1297-1c77-3fb2-03bd-f0acda122d37", "activistCodes": "null", "canvassFileRequestId": 448, "dateExpired": "2018-09-08T16:04:00Z", "surveyQuestions": "null", "webhookUrl": "https://www.nothing.com/", "downloadUrl": "https://ngpvan.blob.core.windows.net/canvass-files-savedlistexport/bf4d1297-1c77-3fb2-03bd-f0acda122d37_2018-09-08T13:03:27.7191831-04:00.csv", # noqa: E501 "savedListId": 517612, "districtFields": "null", "canvassFileRequestGuid": "bf4d1297-1c77-3fb2-03bd-f0acda122d37", "customFields": "null", "type": 4, "exportJobId": 448} m.post(self.van.connection.uri + 'exportJobs', json=json, status_code=201) # expected = [ # 'status', # 'errorCode', # 'exportJobGuid', # 'activistCodes', # 'canvassFileRequestId', # 'dateExpired', # 'surveyQuestions', # 'webhookUrl', # 'downloadUrl', # 'savedListId', # 'districtFields', # 'canvassFileRequestGuid', # 'customFields', # 'type', # 'exportJobId'] self.assertEqual(json, self.van.export_job_create(saved_list_id)) @requests_mock.Mocker() def test_get_export_job(self, m): export_job_id = 448 json = {"status": "Completed", "errorCode": "null", "exportJobGuid": "bf4d1297-1c77-3fb2-03bd-f0acda122d37", "activistCodes": "null", "canvassFileRequestId": 448, "dateExpired": "2018-09-08T16:04:00Z", "surveyQuestions": "null", "webhookUrl": "https://www.nothing.com/", "downloadUrl": "https://ngpvan.blob.core.windows.net/canvass-files-savedlistexport/bf4d1297-1c77-3fb2-03bd-f0acda122d37_2018-09-08T13:03:27.7191831-04:00.csv", # noqa: E501 "savedListId": 517612, "districtFields": "null", "canvassFileRequestGuid": "bf4d1297-1c77-3fb2-03bd-f0acda122d37", "customFields": "null", "type": 4, "exportJobId": 448} # expected = [ # 'status', # 'errorCode', # 'exportJobGuid', # 'activistCodes', # 'canvassFileRequestId', # 'dateExpired', # 'surveyQuestions', # 'webhookUrl', # 'downloadUrl', # 'savedListId', # 'districtFields', # 'canvassFileRequestGuid', # 'customFields', # 'type', # 'exportJobId'] m.get(self.van.connection.uri + f'exportJobs/{export_job_id}', json=json) self.assertEqual(json, self.van.get_export_job(export_job_id))
class TestNGPVAN(unittest.TestCase): def setUp(self): self.van = VAN(os.environ['VAN_API_KEY'], db="MyVoters", raise_for_status=False) @requests_mock.Mocker() def test_find_person(self, m): m.post(self.van.connection.uri + 'people/find', json=find_people_response, status_code=200) person = self.van.find_person(first_name='Bob', last_name='Smith', phone=4142020792) self.assertEqual(person, find_people_response) @requests_mock.Mocker() def test_find_person_json(self, m): json = { "firstName": "Bob", "lastName": "Smith", "phones": [{ "phoneNumber": 4142020792 }] } m.post(self.van.connection.uri + 'people/find', json=find_people_response, status_code=200) person = self.van.find_person_json(match_json=json) self.assertEqual(person, find_people_response) def test_upsert_person(self): pass def test_upsert_person_json(self): pass def test_update_person(self): pass def test_update_person_json(self): pass def test_people_search(self): # Already tested as part of upsert and find person methods pass def test_valid_search(self): # Fails with FN / LN Only self.assertRaises(ValueError, self.van._valid_search, 'Barack', 'Obama', None, None, None, None, None) # Fails with only Zip self.assertRaises(ValueError, self.van._valid_search, 'Barack', 'Obama', None, None, None, None, 60622) # Fails with no street number self.assertRaises(ValueError, self.van._valid_search, 'Barack', 'Obama', None, None, None, 'Pennsylvania Ave', None) # Successful with FN/LN/Email self.van._valid_search('Barack', 'Obama', '*****@*****.**', None, None, None, None) # Successful with FN/LN/DOB/ZIP self.van._valid_search('Barack', 'Obama', '*****@*****.**', None, '2000-01-01', None, 20009) # Successful with FN/LN/Phone self.van._valid_search('Barack', 'Obama', None, 2024291000, None, None, None) @requests_mock.Mocker() def test_get_person(self, m): json = get_person_response # Test works with external ID m.get(self.van.connection.uri + 'people/DWID:15406767', json=json) person = self.van.get_person('15406767', id_type='DWID') self.assertEqual(get_person_response, person) # Test works with vanid m.get(self.van.connection.uri + 'people/19722445', json=json) person = self.van.get_person('19722445') self.assertEqual(get_person_response, person) @requests_mock.Mocker() def test_apply_canvass_result(self, m): # Test a valid attempt m.post(self.van.connection.uri + 'people/2335282/canvassResponses', status_code=204) self.van.apply_canvass_result(2335282, 18) # Test a bad result code json = { 'errors': [{ 'code': 'INVALID_PARAMETER', 'text': "'resultCodeId' must be a valid result code in the current context.", 'properties': ['resultCodeId'] }] } m.post(self.van.connection.uri + 'people/2335282/canvassResponses', json=json, status_code=400) self.assertRaises(HTTPError, self.van.apply_canvass_result, 2335282, 0) # Test a bad vanid json = { 'errors': [{ 'code': 'INTERNAL_SERVER_ERROR', 'text': 'An unknown error occurred', 'referenceCode': '88A111-E2FF8' }] } m.post(self.van.connection.uri + 'people/0/canvassResponses', json=json, status_code=400) self.assertRaises(HTTPError, self.van.apply_canvass_result, 0, 18) # Test a good dwid m.post(self.van.connection.uri + 'people/DWID:2335282/canvassResponses', status_code=204) self.van.apply_canvass_result(2335282, 18, id_type='DWID') @requests_mock.Mocker() def test_apply_survey_question(self, m): # Test valid survey question m.post(self.van.connection.uri + 'people/2335282/canvassResponses', status_code=204) self.van.apply_survey_response(2335282, 351006, 1443891) # Test bad survey response id # json = { # 'errors': [{ # 'code': 'INVALID_PARAMETER', # 'text': ("'surveyResponseId' must be a valid Response to the given " # "Survey Question."), # 'properties': ['responses[0].surveyResponseId'] # }] # } m.post(self.van.connection.uri + 'people/2335282/canvassResponses', status_code=400) self.assertRaises(HTTPError, self.van.apply_survey_response, 2335282, 0, 1443891) # Test bad survey question id # json = { # 'errors': [{ # 'code': 'INVALID_PARAMETER', # 'text': ("'surveyQuestionId' must be a valid Survey Question that is " # "available in the current context."), # 'properties': ['responses[0].surveyQuestionId'] # }] # } m.post(self.van.connection.uri + 'people/2335282/canvassResponses', status_code=400) self.assertRaises(HTTPError, self.van.apply_survey_response, 2335282, 351006, 0) def test_toggle_volunteer_action(self): pass def test_apply_response(self): pass @requests_mock.Mocker() def test_create_relationship(self, m): relationship_id = 12 bad_vanid_1 = 99999 good_vanid_1 = 12345 vanid_2 = 54321 # Bad request m.post(self.van.connection.uri + "people/{}/relationships".format(bad_vanid_1), status_code=404) # Good request m.post(self.van.connection.uri + "people/{}/relationships".format(good_vanid_1), status_code=204) # Test bad input self.assertRaises(HTTPError, self.van.create_relationship, bad_vanid_1, vanid_2, relationship_id) self.assertRaises(HTTPError, self.van.create_relationship, bad_vanid_1, vanid_2, relationship_id) self.van.create_relationship(good_vanid_1, vanid_2, relationship_id) @requests_mock.Mocker() def test_apply_person_code(self, m): vanid = 999 code_id = 888 # Test good request m.post(self.van.connection.uri + f"people/{vanid}/codes", status_code=204) self.van.apply_person_code(vanid, code_id) # Test bad request m.post(self.van.connection.uri + f"people/{vanid}/codes", status_code=404) self.assertRaises(HTTPError, self.van.apply_person_code, vanid, code_id)
class TestNGPVAN(unittest.TestCase): def setUp(self): self.van = VAN(os.environ['VAN_API_KEY'], db="MyVoters") def tearDown(self): pass @requests_mock.Mocker() def test_get_events(self, m): json = { 'count': 6, 'items': [{ "eventId": 1062, "startDate": "2010-05-25T11:00:00-05:00", "codes": "null", "endDate": "2010-05-25T15:00:00-05:00", "name": "Sample", "roles": "null", "isOnlyEditableByCreatingUser": "******", "ticketCategories": "null", "eventType": { "eventTypeId": 29166, "name": "Confirmation Calls" }, "notes": "null", "districtFieldValue": "null", "locations": "null", "shifts": "null", "voterRegistrationBatches": "null", "createdDate": "2010-05-25T11:55:00Z", "financialProgram": "null", "shortName": "Sample", "isPubliclyViewable": "null", "isActive": "true", "description": "This is a sample" }], 'nextPageLink': None } m.get(self.van.connection.uri + 'events', json=json) # Expected Structure expected = [ 'eventId', 'startDate', 'codes', 'endDate', 'name', 'roles', 'isOnlyEditableByCreatingUser', 'ticketCategories', 'eventType', 'notes', 'districtFieldValue', 'locations', 'shifts', 'voterRegistrationBatches', 'createdDate', 'financialProgram', 'shortName', 'isPubliclyViewable', 'isActive', 'description' ] self.assertTrue(validate_list(expected, self.van.get_events())) @requests_mock.Mocker() def test_get_event(self, m): event_id = 1062 json = { "eventId": 1062, "startDate": "2010-05-25T11:00:00-05:00", "codes": "null", "endDate": "2010-05-25T15:00:00-05:00", "name": "Sample", "roles": "null", "isOnlyEditableByCreatingUser": "******", "ticketCategories": "null", "eventType": { "eventTypeId": 29166, "name": "Confirmation Calls" }, "notes": "null", "districtFieldValue": "null", "locations": "null", "shifts": "null", "voterRegistrationBatches": "null", "createdDate": "2010-05-25T11:55:00Z", "financialProgram": "null", "shortName": "Sample", "isPubliclyViewable": "null", "isActive": "true", "description": "This is a sample" } m.get(self.van.connection.uri + 'events/{}'.format(event_id), json=json) self.assertEqual(json, self.van.get_event(event_id)) @requests_mock.Mocker() def test_create_event(self, m): m.post(self.van.connection.uri + 'events', json=750000984, status_code=204) # Test that it doesn't throw and error r = self.van.create_event('Canvass 01', 'Can01', '2016-06-01', '2016-06-02', 296199, [259236], publicly_viewable='True', editable=False) self.assertEqual(r, 750000984) @requests_mock.Mocker() def test_get_event_types(self, m): json = [{ 'eventTypeId': 296199, 'name': 'Block Party', 'canHaveMultipleShifts': False, 'canHaveMultipleLocations': False, 'canHaveGoals': False, 'canHaveRoleMaximums': False, 'canHaveRoleMinimums': False, 'canBeRepeatable': False, 'roles': [{ 'roleId': 259236, 'name': 'Attendee', 'isEventLead': False }, { 'roleId': 259235, 'name': 'Supporter', 'isEventLead': False }, { 'roleId': 259234, 'name': 'Volunteer', 'isEventLead': False }], 'statuses': [{ 'statusId': 4, 'name': 'Invited' }, { 'statusId': 18, 'name': 'Left Msg' }, { 'statusId': 14, 'name': 'Tentative' }, { 'statusId': 3, 'name': 'Declined' }, { 'statusId': 11, 'name': 'Confirmed' }, { 'statusId': 23, 'name': 'Conf Twice' }, { 'statusId': 2, 'name': 'Completed' }, { 'statusId': 15, 'name': 'Walk In' }, { 'statusId': 6, 'name': 'No Show' }, { 'statusId': 29, 'name': 'Texted' }], 'color': '#7F7F7F', 'isAtLeastOneLocationRequired': False, 'defaultLocation': None, 'isSharedWithMasterCommitteeByDefault': False, 'isSharedWithChildCommitteesByDefault': False, 'isOnlineActionsAvailable': False }] m.get(self.van.connection.uri + 'events/types', json=json) expected = [ 'eventTypeId', 'name', 'canHaveMultipleShifts', 'canHaveMultipleLocations', 'canHaveGoals', 'canHaveRoleMaximums', 'canHaveRoleMinimums', 'canBeRepeatable', 'roles', 'statuses', 'color', 'isAtLeastOneLocationRequired', 'defaultLocation', 'isSharedWithMasterCommitteeByDefault', 'isSharedWithChildCommitteesByDefault', 'isOnlineActionsAvailable' ] self.assertTrue(validate_list(expected, self.van.get_event_types()))
class TestNGPVAN(unittest.TestCase): def setUp(self): self.van = VAN(os.environ['VAN_API_KEY'], db="MyVoters", raise_for_status=False) @requests_mock.Mocker() def test_get_changed_entity_resources(self, m): json = [ 'ActivistCodes', 'ContactHistory', 'Contacts', 'ContactsActivistCodes' ] m.get(self.van.connection.uri + 'changedEntityExportJobs/resources', json=json) self.assertEqual(json, self.van.get_changed_entity_resources()) @requests_mock.Mocker() def test_get_changed_entity_resource_fields(self, m): json = [{ 'fieldName': 'ActivistCodeID', 'fieldType': 'N', 'maxTextboxCharacters': None, 'isCoreField': True, 'availableValues': None }, { 'fieldName': 'ActivistCodeType', 'fieldType': 'T', 'maxTextboxCharacters': 20, 'isCoreField': True, 'availableValues': None }, { 'fieldName': 'Campaign', 'fieldType': 'T', 'maxTextboxCharacters': 150, 'isCoreField': True, 'availableValues': None }] m.get(self.van.connection.uri + 'changedEntityExportJobs/fields/ActivistCodes', json=json) assert_matching_tables( Table(json), self.van.get_changed_entity_resource_fields('ActivistCodes')) @requests_mock.Mocker() def test_get_changed_entities(self, m): json = { "dateChangedFrom": "2021-10-10T00:00:00-04:00", "dateChangedTo": "2021-10-11T00:00:00-04:00", "files": [], "message": "Created export job", "code": None, "exportedRecordCount": 0, "exportJobId": 2170181229, "jobStatus": "Pending" } json2 = { "dateChangedFrom": "2021-10-10T00:00:00-04:00", "dateChangedTo": "2021-10-11T00:00:00-04:00", "files": [{ "downloadUrl": "https://box.com/file.csv", "dateExpired": "2021-11-03T15:27:01.8687339-04:00" }], "message": "Finished processing export job", "code": None, "exportedRecordCount": 6110, "exportJobId": 2170181229, "jobStatus": "Complete" } tbl = Table([{'a': 1, 'b': 2}]) m.post(self.van.connection.uri + 'changedEntityExportJobs', json=json) m.get(self.van.connection.uri + 'changedEntityExportJobs/2170181229', json=json2) Table.from_csv = mock.MagicMock() Table.from_csv.return_value = tbl out_tbl = self.van.get_changed_entities('ContactHistory', '2021-10-10') assert_matching_tables(out_tbl, tbl)
def setUp(self): self.van = VAN(os.environ['VAN_API_KEY'], db="MyVoters")
for name, value in config_vars.items( ): # sets variables if provided in this script if value.strip() != "": os.environ[name] = value rs = Redshift( ) # just create Redshift() - VAN connector is created dynamically below # Create dictionary of VAN states and API keys from multiline Civis credential myv_states = { x.split(",")[0]: x.split(",")[1] for x in os.environ['VAN_PASSWORD'].split("\r\n") } myv_keys = { k: VAN(api_key=v, db=os.environ['VAN_DB_NAME']) for k, v in myv_states.items() } # Create simple set of states for insertion into SQL states = "','".join([s for s in myv_keys]) # SQL to pull those needing Activist Code sql = f""" SELECT vb_smartvan_id , vb_vf_source_state , hash , activist_code_id FROM schema.table WHERE vb_vf_source_state IN ({states}) """
class TestSignups(unittest.TestCase): def setUp(self): self.van = VAN(os.environ['VAN_API_KEY'], db="EveryAction", raise_for_status=False) def tearDown(self): pass @requests_mock.Mocker() def test_get_signup_statuses(self, m): m.get(self.van.connection.uri + 'signups/statuses', json=signup_status) # Test events lookup self.assertTrue( validate_list(['statusId', 'name'], self.van.get_signups_statuses(event_id=750000849))) # Test event type lookup self.assertTrue( validate_list( ['statusId', 'name'], self.van.get_signups_statuses(event_type_id=750000849))) @requests_mock.Mocker() def test_get_signups(self, m): json = {'items': [signup], 'nextPageLink': None, 'count': 1} m.get(self.van.connection.uri + 'signups', json=json) self.assertTrue( validate_list(signup_expected, self.van.get_event_signups(event_id=750001004))) self.assertTrue( validate_list(signup_expected, self.van.get_person_signups(vanid=750000849))) @requests_mock.Mocker() def test_get_signup(self, m): event_signup_id = 14285 m.get(self.van.connection.uri + f'signups/{event_signup_id}'.format(), json=signup) self.assertEqual(signup, self.van.get_signup(event_signup_id)) @requests_mock.Mocker() def test_create_signup(self, m): m.post(self.van.connection.uri + 'signups', json=14285, status_code=201) self.assertEqual( self.van.create_signup(100349920, 750001004, 19076, 263920, 11, 3), 14285) @requests_mock.Mocker() def test_update_signup(self, m): # This is two part. It makes a call to get the object and then it updates it event_signup_id = 14285 # Get object route m.get(self.van.connection.uri + f'signups/{event_signup_id}', json=signup) # Update object m.put(self.van.connection.uri + f'signups/{event_signup_id}', status_code=204) self.van.update_signup(event_signup_id, status_id=6)
class TestCodes(unittest.TestCase): def setUp(self): self.van = VAN(os.environ['VAN_API_KEY'], db="MyVoters") def tearDown(self): pass @requests_mock.Mocker() def test_get_codes(self, m): json = { 'items': [{ 'codeId': 1004916, 'parentCodeId': None, 'name': 'Data Entry', 'description': 'for test.', 'codePath': 'Data Entry', 'createdByName': '', 'dateCreated': '2018-07-13T15:16:00Z', 'supportedEntities': None, 'codeType': 'Tag', 'campaign': None, 'contactType': None }], 'nextPageLink': None, 'count': 8 } m.get(self.van.connection.uri + 'codes', json=json) assert_matching_tables(json['items'], self.van.get_codes()) @requests_mock.Mocker() def test_get_code_types(self, m): json = ['Tag', 'SourceCode'] m.get(self.van.connection.uri + 'codeTypes', json=json) self.assertEqual(json, self.van.get_code_types()) @requests_mock.Mocker() def test_create_code(self, m): m.post(self.van.connection.uri + 'codes', json=1004960, status_code=201) # Test that it doesn't throw and error r = self.van.create_code('Test Code', supported_entities=[{ 'name': 'Events', 'is_searchable': True, 'is_applicable': True }]) self.assertEqual(r, 1004960) @requests_mock.Mocker() def test_update_code(self, m): # Test a good input m.put(self.van.connection.uri + 'codes/1004960', status_code=204) self.van.update_code(1004960, name='Test') # Test a bad input m.put(self.van.connection.uri + 'codes/100496Q', status_code=404) self.assertRaises(HTTPError, self.van.update_code, '100496Q') @requests_mock.Mocker() def test_delete_code(self, m): # Test a good input m.delete(self.van.connection.uri + 'codes/1004960', status_code=204) self.van.delete_code(1004960) # Test a bad input m.delete(self.van.connection.uri + 'codes/100496Q', status_code=404) self.assertRaises(HTTPError, self.van.delete_code, '100496Q') @requests_mock.Mocker() def test_get_code_supported_entities(self, m): json = ['Contacts', 'Events', 'Locations'] m.get(self.van.connection.uri + 'codes/supportedEntities', json=json) self.assertEqual(json, self.van.get_code_supported_entities())
set_env_var('AWS_SECRET_ACCESS_KEY', os.environ['AWS_SECRET_ACCESS_KEY']) s3 = S3() # Logging logger = logging.getLogger(__name__) _handler = logging.StreamHandler() _formatter = logging.Formatter('%(levelname)s %(message)s') _handler.setFormatter(_formatter) logger.addHandler(_handler) logger.setLevel('INFO') # Create dictionary of VAN states and API keys from multiline Civis credential myv_states = {x.split(",")[0]: x.split(",")[1] for x in os.environ['VAN_PASSWORD'].split("\r\n")} myv_keys = {k: VAN(api_key=v, db='MyVoters') for k,v in myv_states.items()} # Create simple set of states for insertion into SQL states = "','".join([s for s in myv_keys]) # SQL to pull those needing Activist Code sql = f""" SELECT vb_smartvan_id , vb_vf_source_state , hash , activist_code_id FROM schema.table WHERE vb_vf_source_state IN ({states}) """ records = rs.query(sql)
class TestBulkImport(unittest.TestCase): def setUp(self): self.van = VAN(os.environ['VAN_API_KEY'], db="MyVoters", raise_for_status=False) @requests_mock.Mocker() def test_get_bulk_import_resources(self, m): json = ['Contacts', 'Contributions', 'ActivistCodes', 'ContactsActivistCodes'] m.get(self.van.connection.uri + 'bulkImportJobs/resources', json=json) self.assertEqual(self.van.get_bulk_import_resources(), json) @requests_mock.Mocker() def test_get_bulk_import_job(self, m): m.get(self.van.connection.uri + 'bulkImportJobs/53407', json=bulk_import_job) self.assertEqual(self.van.get_bulk_import_job(53407), bulk_import_job) @requests_mock.Mocker() def test_get_bulk_import_job_results(self, m): results_tbl = Table([['BulkUploadDataID', 'ULFileID', 'PrimaryKey', 'PrimaryKeyType', 'MailingAddress_3581'], ['1', '1983', '101596008', 'VanID', 'Processed']]) bulk_import_job = {'id': 92, 'status': 'Completed', 'resourceType': 'Contacts', 'webhookUrl': None, 'resultFileSizeLimitKb': 5000, 'errors': [], 'resultFiles': [{ 'url': Table.to_csv(results_tbl), 'dateExpired': '2020-09-04T22:07:04.0770295-04:00' }] } m.get(self.van.connection.uri + 'bulkImportJobs/53407', json=bulk_import_job) assert_matching_tables( self.van.get_bulk_import_job_results(53407), results_tbl) @requests_mock.Mocker() def test_get_bulk_import_mapping_types(self, m): m.get(self.van.connection.uri + 'bulkImportMappingTypes', json=mapping_type) assert_matching_tables( self.van.get_bulk_import_mapping_types(), Table(mapping_type)) @requests_mock.Mocker() def test_get_bulk_import_mapping_type(self, m): m.get(self.van.connection.uri + 'bulkImportMappingTypes/ActivistCode', json=mapping_type) self.assertEqual(self.van.get_bulk_import_mapping_type( 'ActivistCode'), mapping_type) @requests_mock.Mocker() def get_bulk_import_mapping_type_fields(self, m): json = [{'name': 'Unsubscribed', 'id': '0', 'parents': None}, {'name': 'Not Subscribed', 'id': '1', 'parents': None}, {'name': 'Subscribed', 'id': '2', 'parents': None}] m.get(self.van.connection.uri + 'bulkImportMappingTypes/Email/EmailSubscriptionStatusId/values') r = self.van.get_bulk_import_mapping_type_fields( 'Email', 'EmailSubscriptionStatusId') self.assertEqual(json, r) @requests_mock.Mocker() def test_post_bulk_import(self, m): # Mock Cloud Storage cloud_storage.post_file = mock.MagicMock() cloud_storage.post_file.return_value = 'https://s3.com/my_file.zip' tbl = Table([['Vanid', 'ActivistCodeID'], [1234, 345345]]) m.post(self.van.connection.uri + 'bulkImportJobs', json={'jobId': 54679}) r = self.van.post_bulk_import(tbl, 'S3', 'ContactsActivistCodes', [{"name": "ActivistCode"}], 'Activist Code Upload', bucket='my-bucket') self.assertEqual(r, 54679) @requests_mock.Mocker() def test_bulk_apply_activist_codes(self, m): # Mock Cloud Storage cloud_storage.post_file = mock.MagicMock() cloud_storage.post_file.return_value = 'https://s3.com/my_file.zip' tbl = Table([['Vanid', 'ActivistCodeID'], [1234, 345345]]) m.post(self.van.connection.uri + 'bulkImportJobs', json={'jobId': 54679}) job_id = self.van.bulk_apply_activist_codes( tbl, url_type="S3", bucket='my-bucket') self.assertEqual(job_id, 54679) @requests_mock.Mocker() def test_bulk_upsert_contacts(self, m): # Mock Cloud Storage cloud_storage.post_file = mock.MagicMock() cloud_storage.post_file.return_value = 'https://s3.com/my_file.zip' tbl = Table([['Vanid', 'email'], [1234, '*****@*****.**']]) m.post(self.van.connection.uri + 'bulkImportJobs', json={'jobId': 54679}) job_id = self.van.bulk_upsert_contacts( tbl, url_type="S3", bucket='my-bucket') self.assertEqual(job_id, 54679)
# ### CODE # Setup import os # noqa: E402 from parsons import VAN, Zoom # noqa: E402 # if variables specified above, sets them as environmental variables for name, value in config_vars.items(): if value.strip() != "": os.environ[name] = value # Code zoom = Zoom() van = VAN(db=VAN_DB) # Gets participants from Zoom meeting participants = zoom.get_past_meeting_participants(ZOOM_MEETING_ID) filtered_participants = participants.select_rows(lambda row: row.duration > MINIMUM_DURATION) # Coalesce the columns into something VAN expects column_map = {"first_name": ["fn", "first", "firstname", "first name"], "last_name": ["ln", "last", "lastname", "last name"], "date_of_birth": ["dob", "date of birth", "birthday"], "email": ["email address", "email_address"], "street_number": ["street number", "street no.", "street no", "street #"], "street_name": ["street name", "street"], "phone": ["phone_number", "phone #", "phone_#", "phone no.", "phone no"], "zip": ["zip5", "zipcode", "zip code"]} filtered_participants.map_and_coalesce_columns(column_map)
class TestScores(unittest.TestCase): def setUp(self): self.van = VAN(os.environ['VAN_API_KEY'], db="MyVoters", raise_for_status=False) @requests_mock.Mocker() def test_get_scores(self, m): json = { u'count': 2, u'items': [{ u'origin': None, u'scoreId': 2716, u'name': u'Democratic Party Support', u'maxValue': 100.0, u'minValue': 1.0, u'state': None, u'shortName': u'Dem Support', u'description': None }], u'nextPageLink': None } m.get(self.van.connection.uri + 'scores', json=json) expected = [ 'origin', 'scoreId', 'name', 'maxValue', 'minValue', 'state', 'shortName', 'description' ] self.assertTrue(validate_list(expected, self.van.get_scores())) @requests_mock.Mocker() def test_get_score(self, m): score_id = 2716 json = { u'origin': None, u'scoreId': 2716, u'name': u'Democratic Party Support', u'maxValue': 100.0, u'minValue': 1.0, u'state': None, u'shortName': u'Dem Support', u'description': None } m.get(self.van.connection.uri + 'scores/{}'.format(score_id), json=json) self.assertEqual(json, self.van.get_score(score_id)) @requests_mock.Mocker() def test_get_score_updates(self, m): json = { 'items': [{ 'scoreUpdateId': 58319, 'score': { 'scoreId': 29817, 'name': 'TargetSmart Gun Ownership', 'shortName': None, 'description': None, 'minValue': 0.0, 'maxValue': 100.0, 'state': 'MT', 'origin': None }, 'updateStatistics': { 'totalRows': 856644, 'duplicateRows': 0, 'matchedRows': 856644, 'matchPercent': 100.0, 'increasedBy': 441264, 'decreasedBy': 280588, 'nulledOut': 3649, 'added': 115129, 'outOfRange': 0, 'badValues': 0, 'maxValue': 95.9, 'minValue': 11.2, 'averageValue': 72.3338, 'medianValue': 76.3 }, 'loadStatus': 'Completed', 'dateProcessed': '2019-09-10T02:07:00Z' }], 'nextPageLink': None, 'count': 306 } m.get(self.van.connection.uri + 'scoreUpdates', json=json) expected = [ 'scoreUpdateId', 'loadStatus', 'dateProcessed', 'added', 'averageValue', 'badValues', 'decreasedBy', 'duplicateRows', 'increasedBy', 'matchPercent', 'matchedRows', 'maxValue', 'medianValue', 'minValue', 'nulledOut', 'outOfRange', 'totalRows', 'description', 'maxValue', 'minValue', 'name', 'origin', 'scoreId', 'shortName', 'state' ] self.assertTrue(validate_list(expected, self.van.get_score_updates())) @requests_mock.Mocker() def test_get_score_update(self, m): score_update_id = 27892 json = { "loadStatus": "Canceled", "updateStatistics": { "increasedBy": 1, "nulledOut": 1, "added": 0, "matchedRows": 4, "matchPercent": 100.0, "outOfRange": 0, "badValues": 1, "totalRows": 4, "maxValue": 30.0, "medianValue": 15.0, "minValue": 10.0, "duplicateRows": "null", "averageValue": 20.0, "decreasedBy": 2 }, "score": { "origin": "null", "scoreId": 2716, "name": "Democratic Party Support", "maxValue": 100.0, "minValue": 1.0, "state": "null", "shortName": "null", "description": "null" }, "dateProcessed": "null", "scoreUpdateId": 27892 } m.get(self.van.connection.uri + f'scoreUpdates/{score_update_id}', json=json) # expected = ['loadStatus', 'updateStatistics', 'score', 'dateProcessed', 'scoreUpdateId'] self.assertEqual(json, self.van.get_score_update(score_update_id)) @requests_mock.Mocker() def test_update_score_status(self, m): score_update_id = 27892 m.patch(self.van.connection.uri + 'scoreUpdates/{}'.format(score_update_id), status_code=204) # Test bad input self.assertRaises(ValueError, self.van.update_score_status, score_update_id, 'not a thing.') # Test good input self.assertTrue( self.van.update_score_status(score_update_id, 'approved')) @requests_mock.Mocker() def test_upload_scores(self, m): # Mock Cloud Storage cloud_storage.post_file = mock.MagicMock() cloud_storage.post_file.return_value = 'https://box.com/my_file.zip' # Test uploading a job tbl = Table([['vanid', 'col'], ['1', '.5']]) json = {'jobId': 9749} m.post(self.van.connection.uri + 'FileLoadingJobs', json=json, status_code=201) self.van.upload_scores(tbl, [{ 'score_id': 9999, 'score_column': 'col' }], url_type='S3') @requests_mock.Mocker() def test_create_file_load(self, m): file_name = 'test_scores.csv' file_url_good = 'http://tmc.org/test_scores.zip' # file_url_bad = 'http://tmc.org/test_scores' columns = ['vanid', 'score'] id_column = 'vanid' id_type = 'VANID' score_id = 2716 score_column = 'score' bad_delimiter = '*' json = {'jobId': 9749} m.post(self.van.connection.uri + 'FileLoadingJobs', json=json, status_code=201) # Test bad delimiter self.assertRaises(ValueError, self.van.create_file_load, file_name, file_url_good, columns, id_column, id_type, score_id, score_column, delimiter=bad_delimiter) # Test good request self.assertEqual( json['jobId'], self.van.create_file_load(file_name, file_url_good, columns, id_column, id_type, score_id, score_column))
def setUp(self): self.van = VAN(os.environ['VAN_API_KEY'], db="EveryAction", raise_for_status=False)
def setUp(self): self.van = VAN(os.environ['VAN_API_KEY'], db="MyVoters", raise_for_status=False)
class TestNGPVAN(unittest.TestCase): def setUp(self): self.van = VAN(os.environ['VAN_API_KEY'], db="MyVoters", raise_for_status=False) def tearDown(self): pass @requests_mock.Mocker() def test_get_canvass_responses_contact_types(self, m): json = { "name": "Auto Dial", "contactTypeId": 19, "channelTypeName": "Phone" } m.get(self.van.connection.uri + 'canvassResponses/contactTypes', json=json) assert_matching_tables(Table(json), self.van.get_canvass_responses_contact_types()) @requests_mock.Mocker() def test_get_canvass_responses_input_types(self, m): json = {"inputTypeId": 11, "name": "API"} m.get(self.van.connection.uri + 'canvassResponses/inputTypes', json=json) assert_matching_tables(Table(json), self.van.get_canvass_responses_input_types()) @requests_mock.Mocker() def test_get_canvass_responses_result_codes(self, m): json = { "shortName": "BZ", "resultCodeId": 18, "name": "Busy", "mediumName": "Busy" } m.get(self.van.connection.uri + 'canvassResponses/resultCodes', json=json) assert_matching_tables(Table(json), self.van.get_canvass_responses_result_codes()) @requests_mock.Mocker() def test_get_survey_questions(self, m): json = { u'count': 67, u'items': [{ "status": "Active", "responses": [{ "shortName": "1", "surveyResponseId": 1288926, "name": "1-Strong Walz", "mediumName": "1" }, { "shortName": "2", "surveyResponseId": 1288928, "name": "2-Lean Walz", "mediumName": "2" }], "scriptQuestion": "Who do you support for Governor?", "name": "MN Governor Gen", "surveyQuestionId": 311838, "mediumName": "MNGovG", "shortName": "MGG", "type": "Candidate", "cycle": 2018 }], u'nextPageLink': None } m.get(self.van.connection.uri + 'surveyQuestions', json=json) expected = [ 'status', 'responses', 'scriptQuestion', 'name', 'surveyQuestionId', 'mediumName', 'shortName', 'type', 'cycle' ] self.assertTrue( validate_list(expected, self.van.get_survey_questions())) @requests_mock.Mocker() def test_get_supporter_groups(self, m): json = { "items": [ { "id": 12, "name": "tmc", "description": "A fun group." }, { "id": 13, "name": "tmc", "description": "A fun group." }, ], "nextPageLink": None, "count": 3 } m.get(self.van.connection.uri + 'supporterGroups', json=json) ['id', 'name', 'description'] self.van.get_supporter_groups() @requests_mock.Mocker() def test_get_supporter_group(self, m): json = {"id": 12, "name": "tmc", "description": "A fun group."} m.get(self.van.connection.uri + 'supporterGroups/12', json=json) # Test that columns are expected columns self.assertEqual(self.van.get_supporter_group(12), json) @requests_mock.Mocker() def test_delete_supporter_group(self, m): # Test good input good_supporter_group_id = 5 good_ep = f'supporterGroups/{good_supporter_group_id}' m.delete(self.van.connection.uri + good_ep, status_code=204) self.van.delete_supporter_group(good_supporter_group_id) # Test bad input raises bad_supporter_group_id = 999 # bad_vanid = 99999 bad_ep = f'supporterGroups/{bad_supporter_group_id}' m.delete(self.van.connection.uri + bad_ep, status_code=404) self.assertRaises(HTTPError, self.van.delete_supporter_group, bad_supporter_group_id) @requests_mock.Mocker() def test_add_person_supporter_group(self, m): # Test good input good_supporter_group_id = 5 good_vanid = 12345 good_uri = f'supporterGroups/{good_vanid}/people/{good_supporter_group_id}' m.put(self.van.connection.uri + good_uri, status_code=204) self.van.add_person_supporter_group(good_vanid, good_supporter_group_id) # Test bad input bad_supporter_group_id = 999 bad_vanid = 99999 bad_uri = f'supporterGroups/{bad_vanid}/people/{bad_supporter_group_id}' m.put(self.van.connection.uri + bad_uri, status_code=404) self.assertRaises(HTTPError, self.van.add_person_supporter_group, bad_vanid, bad_supporter_group_id) @requests_mock.Mocker() def test_delete_person_supporter_group(self, m): # Test good input good_supporter_group_id = 5 good_vanid = 12345 good_ep = f'supporterGroups/{good_vanid}/people/{good_supporter_group_id}' m.delete(self.van.connection.uri + good_ep, status_code=204) self.van.delete_person_supporter_group(good_vanid, good_supporter_group_id) # Test bad input raises bad_supporter_group_id = 999 bad_vanid = 99999 bad_ep = f'supporterGroups/{bad_vanid}/people/{bad_supporter_group_id}' m.delete(self.van.connection.uri + bad_ep, status_code=404) self.assertRaises(HTTPError, self.van.delete_person_supporter_group, bad_vanid, bad_supporter_group_id)