def test_department_name_unique_required(self, db): Department.create(name="name") # Enters username that is already registered form = NewDepartmentForm(department_name="name") assert form.validate() is False assert 'Department name already registered.' in form.department_name.errors
def test_only_department_user_can_access_non_public_datasets(self, testapp): # create a department department = Department.create(name="IM Police Department", short_name="IMPD", load_defaults=True) department.is_public_citizen_complaints = False department.is_public_use_of_force_incidents = False department.is_public_officer_involved_shootings = False department.is_public_assaults_on_officers = False # log in under a different department, datasets should not be accessible bad_department = Department.create(name="B Police Department", short_name="BPD", load_defaults=False) create_and_log_in_user(testapp, bad_department) testapp.get("/department/{}/complaints/".format(department.short_name), status=403) testapp.get("/department/{}/schema/complaints/".format(department.short_name), status=403) testapp.get("/department/{}/complaints.csv".format(department.id), status=403) testapp.get("/department/{}/useofforce/".format(department.short_name), status=403) testapp.get("/department/{}/schema/useofforce/".format(department.short_name), status=403) testapp.get("/department/{}/uof.csv".format(department.id), status=403) testapp.get("/department/{}/officerinvolvedshootings/".format(department.short_name), status=403) testapp.get("/department/{}/schema/officerinvolvedshootings/".format(department.short_name), status=403) testapp.get("/department/{}/ois.csv".format(department.id), status=403) testapp.get("/department/{}/assaultsonofficers/".format(department.short_name), status=403) testapp.get("/department/{}/schema/assaultsonofficers/".format(department.short_name), status=403) testapp.get("/department/{}/assaultsonofficers.csv".format(department.id), status=403)
def test_csv_filtered_by_dept(self, testapp): # create a department department1 = Department.create(name="IM Police Department", short_name="IMPD", load_defaults=False) department2 = Department.create(name="B Police Department", short_name="BPD", load_defaults=False) incidentclass1 = getattr( importlib.import_module("comport.data.models"), "UseOfForceIncident{}".format(department1.short_name)) incidentclass2 = getattr( importlib.import_module("comport.data.models"), "UseOfForceIncident{}".format(department2.short_name)) incidentclass1.create(opaque_id="123ABC", department_id=department1.id) incidentclass2.create(opaque_id="123XYZ", department_id=department2.id) response1 = testapp.get("/department/{}/uof.csv".format( department1.id)) response2 = testapp.get("/department/{}/uof.csv".format( department2.id)) incidents1 = list(csv.DictReader(io.StringIO(response1.text))) incidents2 = list(csv.DictReader(io.StringIO(response2.text))) assert len(incidents1) == 1 and len(incidents2) == 1 assert incidents1[0]['id'] == '123ABC' and incidents2[0][ 'id'] == '123XYZ'
def test_department_short_name_unique_required(self, db): ''' The form won't allow creation of a duplicate department short name. ''' test_name = "Any Police Department" test_short_name = "APD" Department.create(name=test_name, short_name=test_short_name) form = NewDepartmentForm(department_name="Another Police Department", department_short_name=test_short_name) assert form.validate() is False assert 'The department short name "{}" is already registered.'.format(test_short_name) in form.department_short_name.errors
def test_department_short_name_unique_required(self, db): ''' The form won't allow creation of a duplicate department short name. ''' test_name = "Any Police Department" test_short_name = "APD" Department.create(name=test_name, short_name=test_short_name) form = NewDepartmentForm(department_name="Another Police Department", department_short_name=test_short_name) assert form.validate() is False assert 'The department short name "{}" is already registered.'.format(test_short_name) in form.department_short_name.errors
def add_department(): form = NewDepartmentForm(request.form) if request.method == 'POST': if form.validate_on_submit(): Department.create(name=form.department_name.data) flash('Department %s created.' % form.department_name.data, 'info') return redirect(url_for('admin.admin_dashboard')) else: flash_errors(form) return render_template("admin/newDepartment.html", form=form)
def test_non_public_depts_display_for_users_with_access(self, testapp): ''' Users can see links to datasets they're allowed to access on the front page ''' impd = Department.create(name="I Police Department", short_name="IMPD", is_public=True) UseOfForceIncidentIMPD.create(department_id=impd.id, opaque_id="12345abcde") bpd = Department.create(name="B Police Department", short_name="BPD", is_public=False) UseOfForceIncidentBPD.create(department_id=bpd.id, opaque_id="12345abcde") lmpd = Department.create(name="LM Police Department", short_name="LMPD", is_public=False) UseOfForceIncidentLMPD.create(department_id=lmpd.id, opaque_id="12345abcde") # A non logged-in user can only see the public department response = testapp.get("/", status=200) soup = BeautifulSoup(response.text) assert soup.find("a", href="/department/IMPD/useofforce") is not None assert soup.find("a", href="/department/BPD/useofforce") is None assert soup.find("a", href="/department/LMPD/useofforce") is None # A user associated with a particular department can see that department's # available datasets when logged in create_and_log_in_user(testapp=testapp, department=bpd, username="******") response = testapp.get("/", status=200) soup = BeautifulSoup(response.text) assert soup.find("a", href="/department/IMPD/useofforce") is not None assert soup.find("a", href="/department/BPD/useofforce") is not None assert soup.find("a", href="/department/LMPD/useofforce") is None # A user with admin access can see all departments' available datasets create_and_log_in_user(testapp=testapp, department=impd, rolename='admin', username="******") response = testapp.get("/", status=200) soup = BeautifulSoup(response.text) assert soup.find("a", href="/department/IMPD/useofforce") is not None assert soup.find("a", href="/department/BPD/useofforce") is not None assert soup.find("a", href="/department/LMPD/useofforce") is not None # Log out and only the public department should be visible testapp.get(url_for('public.logout')).follow() response = testapp.get("/", status=200) soup = BeautifulSoup(response.text) assert soup.find("a", href="/department/IMPD/useofforce") is not None assert soup.find("a", href="/department/BPD/useofforce") is None assert soup.find("a", href="/department/LMPD/useofforce") is None
def add_department(): form = NewDepartmentForm(request.form) if request.method == 'POST': if form.validate_on_submit(): Department.create(name=form.department_name.data, short_name=form.department_short_name.data) flash('Department %s created.' % form.department_name.data, 'info') return redirect(url_for('admin.admin_dashboard')) else: flash_errors(form) return render_template("admin/newDepartment.html", form=form)
def test_multiple_depts_display(self, testapp): impd = Department.create(name="I Police Department", short_name="IMPD", is_public=True) UseOfForceIncidentIMPD.create(department_id=impd.id, opaque_id="12345abcde") bpd = Department.create(name="B Police Department", short_name="BPD", is_public=True) UseOfForceIncidentBPD.create(department_id=bpd.id, opaque_id="12345abcde") lmpd = Department.create(name="LM Police Department", short_name="LMPD", is_public=False) UseOfForceIncidentLMPD.create(department_id=lmpd.id, opaque_id="12345abcde") response = testapp.get("/", status=200) soup = BeautifulSoup(response.text) assert soup.find("a", href="/department/IMPD/useofforce") is not None assert soup.find("a", href="/department/BPD/useofforce") is not None assert soup.find("a", href="/department/LMPD/useofforce") is None
def test_updated_text_on_schema_pages(self, testapp): ''' The notice of the last time a dataset was updated is on all schema pages ''' department = Department.create(name="B Police Department", short_name="BPD", is_public=True) CitizenComplaintBPD.create(department_id=department.id, opaque_id="12345abcde") UseOfForceIncidentBPD.create(department_id=department.id, opaque_id="23456bcdef") OfficerInvolvedShootingBPD.create(department_id=department.id, opaque_id="34567cdefg") SRDepartment = Department.create(name="SR Police Department", short_name="SRPD", is_public=True) PursuitSRPD.create(department_id=SRDepartment.id, opaque_id="45678defgh") extractor_password = '******' bpd_extractor, envs = Extractor.from_department_and_password( department=department, password=extractor_password) bpd_extractor.last_contact = datetime.datetime(2012, 9, 16) srpd_extractor, envs = Extractor.from_department_and_password( department=SRDepartment, password=extractor_password) srpd_extractor.last_contact = datetime.datetime(2014, 11, 2) response = testapp.get("/department/BPD/schema/complaints/") soup = BeautifulSoup(response.text) updated_span = soup.find("span", {"class": "updated"}) assert updated_span is not None assert "Last Updated September 16, 2012" == updated_span.text response = testapp.get("/department/BPD/schema/useofforce/") soup = BeautifulSoup(response.text) updated_span = soup.find("span", {"class": "updated"}) assert updated_span is not None assert "Last Updated September 16, 2012" == updated_span.text response = testapp.get( "/department/BPD/schema/officerinvolvedshootings/") soup = BeautifulSoup(response.text) updated_span = soup.find("span", {"class": "updated"}) assert updated_span is not None assert "Last Updated September 16, 2012" == updated_span.text response = testapp.get("/department/SRPD/schema/pursuits/") soup = BeautifulSoup(response.text) updated_span = soup.find("span", {"class": "updated"}) assert updated_span is not None assert "Last Updated November 02, 2014" == updated_span.text
def test_only_department_user_can_access_non_public_datasets( self, testapp): # create a department department = Department.create(name="IM Police Department", short_name="IMPD", load_defaults=True) department.is_public_citizen_complaints = False department.is_public_use_of_force_incidents = False department.is_public_officer_involved_shootings = False department.is_public_assaults_on_officers = False # log in under a different department, datasets should not be accessible bad_department = Department.create(name="B Police Department", short_name="BPD", load_defaults=False) create_and_log_in_user(testapp, bad_department) testapp.get("/department/{}/complaints/".format(department.short_name), status=403) testapp.get("/department/{}/schema/complaints/".format( department.short_name), status=403) testapp.get("/department/{}/complaints.csv".format(department.id), status=403) testapp.get("/department/{}/useofforce/".format(department.short_name), status=403) testapp.get("/department/{}/schema/useofforce/".format( department.short_name), status=403) testapp.get("/department/{}/uof.csv".format(department.id), status=403) testapp.get("/department/{}/officerinvolvedshootings/".format( department.short_name), status=403) testapp.get("/department/{}/schema/officerinvolvedshootings/".format( department.short_name), status=403) testapp.get("/department/{}/ois.csv".format(department.id), status=403) testapp.get("/department/{}/assaultsonofficers/".format( department.short_name), status=403) testapp.get("/department/{}/schema/assaultsonofficers/".format( department.short_name), status=403) testapp.get("/department/{}/assaultsonofficers.csv".format( department.id), status=403)
def test_delete_records(self): """ Delete incidents_updated records using the delete_records method. """ # create a couple of departments department_bpd = Department.create(name="B Police Department", short_name="BPD") department_impd = Department.create(name="IM Police Department", short_name="IMPD") # create some 'incidents updated' records uof_type = "uof" ois_type = "ois" ids_and_types = [ ("123abc", uof_type, department_bpd.id), ("234bcd", uof_type, department_bpd.id), ("345cde", ois_type, department_bpd.id), ("456def", uof_type, department_impd.id), ("567efg", uof_type, department_impd.id), ("678fgh", ois_type, department_impd.id), ] for opaque_id, use_type, department_id in ids_and_types: IncidentsUpdated.create(department_id=department_id, opaque_id=opaque_id, incident_type=use_type) # verify that the records were saved as expected assert len(IncidentsUpdated.query.all()) == len(ids_and_types) assert len(IncidentsUpdated.query.filter_by(department_id=department_bpd.id).all()) == 3 assert len(IncidentsUpdated.query.filter_by(department_id=department_impd.id).all()) == 3 assert len(IncidentsUpdated.query.filter_by(incident_type=uof_type).all()) == 4 assert len(IncidentsUpdated.query.filter_by(incident_type=ois_type).all()) == 2 # delete the impd records num_deleted = IncidentsUpdated.delete_records(department_id=department_impd.id) assert num_deleted == len(ids_and_types) / 2 # verify the results assert len(IncidentsUpdated.query.all()) == len(ids_and_types) - num_deleted assert len(IncidentsUpdated.query.filter_by(department_id=department_bpd.id).all()) == 3 assert len(IncidentsUpdated.query.filter_by(department_id=department_impd.id).all()) == 0 assert len(IncidentsUpdated.query.filter_by(incident_type=uof_type).all()) == 2 assert len(IncidentsUpdated.query.filter_by(incident_type=ois_type).all()) == 1 # delete the bpd uof records num_deleted = IncidentsUpdated.delete_records(department_id=department_bpd.id, incident_type=uof_type) assert num_deleted == 2 # verify the results assert len(IncidentsUpdated.query.all()) == 1 assert len(IncidentsUpdated.query.filter_by(department_id=department_bpd.id).all()) == 1 assert len(IncidentsUpdated.query.filter_by(incident_type=uof_type).all()) == 0 assert len(IncidentsUpdated.query.filter_by(incident_type=ois_type).all()) == 1
def test_post_assaults_data(self, testapp): ''' New assaults data from the extractor is processed as expected. ''' # Set up the extractor department = Department.create(name="IM Police Department", short_name="IMPD", load_defaults=False) extractor, envs = Extractor.from_department_and_password(department=department, password="******") # Set the correct authorization testapp.authorization = ('Basic', (extractor.username, 'password')) # Get a generated list of assault descriptions from the JSON test client test_client = JSONTestClient() assault_count = 1 assault_data = test_client.get_prebaked_assaults(last=assault_count) # post the json to the assault URL response = testapp.post_json("/data/assaults", params={'month': 0, 'year': 0, 'data': assault_data}) # assert that we got the expected reponse assert response.status_code == 200 assert response.json_body['updated'] == 0 assert response.json_body['added'] == assault_count # check the assault incident in the database against the data that was sent cleaner = Cleaners() sent_assault = cleaner.capitalize_incident(assault_data[0]) check_assault = AssaultOnOfficerIMPD.query.filter_by(opaque_id=sent_assault['opaqueId']).first() assert check_assault.service_type == sent_assault['serviceType'] assert check_assault.force_type == sent_assault['forceType'] assert check_assault.assignment == sent_assault['assignment'] assert check_assault.arrest_made == sent_assault['arrestMade'] assert check_assault.officer_injured == sent_assault['officerInjured'] assert check_assault.officer_killed == sent_assault['officerKilled'] assert check_assault.report_filed == sent_assault['reportFiled']
def test_submitting_schema_edit_form_redirects_to_preview(self, testapp): ''' Submitting the form to edit a schema field changes the correct value in the database ''' department = Department.create(name="B Police Department", short_name="BPD", load_defaults=True) # set up a user create_and_log_in_user(testapp, department) # make a request to specific front page response = testapp.get("/department/{}/edit/schema/complaints".format(department.id)) assert response.status_code == 200 # submit new title & content assert 'editShiftTitleContentAndOrder' in response.forms form = response.forms['editShiftTitleContentAndOrder'] new_title = "A New Data Field Title" new_content = "A Short Definition of this Data Field" new_order = 99 form['chart_title'] = new_title form['chart_content'] = new_content form['chart_order'] = new_order response = form.submit() # the response should be a redirect assert response.status_code == 302 # the location of the redirect should be the preview page parsed = urlparse(response.location) assert parsed.path == "/department/{}/preview/schema/complaints".format(department.id)
def test_edit_and_preview_links_on_department_admin_page(sefl, testapp): ''' There are links to preview & edit main and schema pages from the department admin page. ''' department = Department.create(name="B Police Department", short_name="BPD", load_defaults=True) # set up a user create_and_log_in_user(testapp, department) # make a request to specific front page response = testapp.get("/department/{}".format(department.id)) assert response.status_code == 200 soup = BeautifulSoup(response.text) assert soup.find("a", href="{}/preview/useofforce".format(department.id)) is not None assert soup.find("a", href="{}/preview/complaints".format(department.id)) is not None assert soup.find("a", href="{}/preview/ois".format(department.id)) is not None assert soup.find("a", href="{}/preview/assaultsonofficers".format(department.id)) is not None assert soup.find("a", href="{}/edit/useofforce".format(department.id)) is not None assert soup.find("a", href="{}/edit/complaints".format(department.id)) is not None assert soup.find("a", href="{}/edit/ois".format(department.id)) is not None assert soup.find("a", href="{}/edit/assaultsonofficers".format(department.id)) is not None assert soup.find("a", href="{}/preview/schema/useofforce".format(department.id)) is not None assert soup.find("a", href="{}/preview/schema/complaints".format(department.id)) is not None assert soup.find("a", href="{}/preview/schema/ois".format(department.id)) is not None assert soup.find("a", href="{}/preview/schema/assaultsonofficers".format(department.id)) is not None assert soup.find("a", href="{}/edit/schema/useofforce".format(department.id)) is not None assert soup.find("a", href="{}/edit/schema/complaints".format(department.id)) is not None assert soup.find("a", href="{}/edit/schema/ois".format(department.id)) is not None assert soup.find("a", href="{}/edit/schema/assaultsonofficers".format(department.id)) is not None
def test_submitting_schema_intro_field_value(self, testapp): ''' Submitting the form to edit a schema intro field changes the expected value in the database and not others ''' department = Department.create(name="B Police Department", short_name="BPD", load_defaults=True) # set up a user create_and_log_in_user(testapp, department) # make a request to specific front page response = testapp.get("/department/{}/edit/schema/complaints".format(department.id)) assert response.status_code == 200 assert 'editIntro' in response.forms form = response.forms['editIntro'] new_content = "A Short Definition of this Data Field" form['chart_content'] = new_content checkblock = ChartBlock.query.filter_by(slug="complaints-schema-introduction", department_id=department.id).first() title = checkblock.title order = checkblock.order response = form.submit().follow() assert response.status_code == 200 checkblock2 = ChartBlock.query.filter_by(slug="complaints-schema-introduction", department_id=department.id).first() assert checkblock.content == new_content assert title == checkblock2.title assert order == checkblock2.order
def test_editing_useofforce_schema_field_value(self, testapp): ''' Submitting the form to edit a schema field changes the correct value in the database ''' department = Department.create(name="B Police Department", short_name="BPD", load_defaults=True) # set up a user create_and_log_in_user(testapp, department) # make a request to specific front page response = testapp.get("/department/{}/edit/schema/useofforce".format(department.id)) assert response.status_code == 200 assert 'editShiftTitleContentAndOrder' in response.forms form = response.forms['editShiftTitleContentAndOrder'] new_title = "A New Data Field Title" new_content = "A Short Definition of this Data Field" new_order = 99 form['chart_title'] = new_title form['chart_content'] = new_content form['chart_order'] = new_order response = form.submit().follow() assert response.status_code == 200 checkblock = ChartBlock.query.filter_by(slug="uof-schema-field-shift").first() assert checkblock.title == new_title assert checkblock.content == new_content assert checkblock.order == len(department.get_blocks_by_slug_startswith("uof-schema-field-")) - 1
def test_department_can_be_set_private(self): # create a department department = Department.create(name="IM Police Department", short_name="IMPD", is_public=False, load_defaults=False) assert not department.is_public
def test_schema_chart_block_order(self): ''' Set and get complaint chart blocks. ''' department = Department.create(name="IM Police Department", short_name="IMPD", load_defaults=True) # get complaint schema blocks before_blocks = department.get_complaint_schema_blocks() # make sure our test will be valid assert len(before_blocks['blocks']) > 2 assert before_blocks['blocks'][0].order < before_blocks['blocks'][1].order assert before_blocks['blocks'][1].order < 100 assert before_blocks['blocks'][-1].order < 100 # change the order of the first block to 100 block = before_blocks['blocks'][0] block.order = 100 block.save() # get the blocks again and test the order after_blocks = department.get_complaint_schema_blocks() assert before_blocks['blocks'][1].order == after_blocks['blocks'][0].order assert before_blocks['blocks'][1].slug == after_blocks['blocks'][0].slug assert after_blocks['blocks'][-1].order == 100 assert before_blocks['blocks'][0].slug == after_blocks['blocks'][-1].slug
def test_get_ois_blocks(self): ''' Set and get ois chart blocks. ''' department = Department.create(name="Ink Mark Police Department", short_name="IMPD", load_defaults=False) # create & append chart blocks with the expected slugs ois_intro = ChartBlock(title="INTRO", dataset="intros", slug="ois-introduction") ois_bid = ChartBlock(title="BYASSIGNMENT", dataset="bid", slug="ois-by-inc-district") ois_wt = ChartBlock(title="WEAPONTYPE", dataset="weapontype", slug="ois-weapon-type") ois_od = ChartBlock(title="OFFICERDEMOS", dataset="od", slug="officer-demographics") ois_race = ChartBlock(title="RACE", dataset="race", slug="ois-race") department.chart_blocks.append(ois_intro) department.chart_blocks.append(ois_bid) department.chart_blocks.append(ois_wt) department.chart_blocks.append(ois_od) department.chart_blocks.append(ois_race) department.save() # verify that the blocks are returned in the expected structure ois_blocks = department.get_ois_blocks() assert ois_blocks['introduction'] == ois_intro assert ois_blocks['first-block'] == ois_bid assert ois_blocks['blocks'][0] == ois_wt assert ois_blocks['blocks'][1] == ois_od assert ois_blocks['blocks'][2] == ois_race
def test_get_assaults_blocks(self): ''' Set and get ois chart blocks. ''' department = Department.create( name="Inopportune Moment Police Department", short_name="IMPD", load_defaults=False) # create & append chart blocks with the expected slugs assault_intro = ChartBlock(title="INTRO", dataset="intros", slug="assaults-introduction") assault_bst = ChartBlock(title="BYINCDISTRICT", dataset="bst", slug="assaults-by-service-type") assault_bft = ChartBlock(title="WEAPONTYPE", dataset="bft", slug="assaults-by-force-type") assault_bo = ChartBlock(title="OFFICERDEMOS", dataset="bo", slug="assaults-by-officer") department.chart_blocks.append(assault_intro) department.chart_blocks.append(assault_bst) department.chart_blocks.append(assault_bft) department.chart_blocks.append(assault_bo) department.save() # verify that the blocks are returned in the expected structure assault_blocks = department.get_assaults_blocks() assert assault_blocks['introduction'] == assault_intro assert assault_blocks['first-block'] == assault_bst assert assault_blocks['blocks'][0] == assault_bft assert assault_blocks['blocks'][1] == assault_bo
def test_get_complaint_blocks(self): ''' Set and get complaint chart blocks. ''' department = Department.create(name="B Police Department", short_name="BPD", load_defaults=False) # create & append chart blocks with the expected slugs complaint_intro = ChartBlock(title="INTRO", dataset="intros", slug="complaints-introduction") complaint_bm = ChartBlock(title="BYMONTH", dataset="bymonth", slug="complaints-by-month") complaint_bya = ChartBlock(title="BYALLEGATION", dataset="bya", slug="complaints-by-allegation") complaint_bdis = ChartBlock(title="BYDISPOSITION", dataset="bdis", slug="complaints-by-disposition") complaint_bass = ChartBlock(title="BYPRECINCT", dataset="bpre", slug="complaints-by-assignment") complaint_od = ChartBlock(title="OFFICERDEMOS", dataset="od", slug="officer-demographics") complaint_bde = ChartBlock(title="BYDEMO", dataset="bde", slug="complaints-by-demographic") complaint_bof = ChartBlock(title="BYOFFICER", dataset="bof", slug="complaints-by-officer-with-cap") department.chart_blocks.append(complaint_intro) department.chart_blocks.append(complaint_bm) department.chart_blocks.append(complaint_bya) department.chart_blocks.append(complaint_bdis) department.chart_blocks.append(complaint_bass) department.chart_blocks.append(complaint_od) department.chart_blocks.append(complaint_bde) department.chart_blocks.append(complaint_bof) department.save() # verify that the blocks are returned in the expected structure complaint_blocks = department.get_complaint_blocks() assert complaint_blocks['introduction'] == complaint_intro assert complaint_blocks['first-block'] == complaint_bm assert complaint_blocks['blocks'][0] == complaint_bya assert complaint_blocks['blocks'][1] == complaint_bdis assert complaint_blocks['blocks'][2] == complaint_bass assert complaint_blocks['blocks'][3] == complaint_od assert complaint_blocks['blocks'][4] == complaint_bde assert complaint_blocks['blocks'][5] == complaint_bof
def test_correct_complaint_cap (self, testapp): ''' New complaint data from the extractor is processed as expected. ''' # Set up the extractor department = Department.create(name="IM Police Department", short_name="IMPD", load_defaults=False) extractor, envs = Extractor.from_department_and_password(department=department, password="******") # Set the correct authorization testapp.authorization = ('Basic', (extractor.username, 'password')) # Get a generated list of complaint descriptions from the JSON test client test_client = JSONTestClient() complaint_count = 1 complaint_data = test_client.get_prebaked_complaints(last=complaint_count) complaint_data[0]["allegation"] = "Rude, demeaning, or affronting language" # post the json to the complaint URL response = testapp.post_json("/data/complaints", params={'month': 0, 'year': 0, 'data': complaint_data}) # assert that we got the expected reponse assert response.status_code == 200 assert response.json_body['updated'] == 0 assert response.json_body['added'] == complaint_count # check the complaint incident in the database against the data that was sent cleaner = Cleaners() sent_complaint = cleaner.capitalize_incident(complaint_data[0]) check_complaint = CitizenComplaintIMPD.query.filter_by(opaque_id=sent_complaint['opaqueId']).first() assert check_complaint.allegation == "Rude, Demeaning, or Affronting Language" with open("scratch.txt", "w") as text_file: text_file.write("Complaint Data: {} ".format(check_complaint.allegation))
def test_get_assaults_schema_blocks(self): ''' Set and get assaults schema chart blocks. ''' department = Department.create(name="IM Police Department", short_name="IMPD", load_defaults=False) # create & append chart blocks with the expected slugs assaults_intro = ChartBlock(title="INTRO", dataset="intros", slug="assaults-schema-introduction") assaults_fid = ChartBlock(title="FIELDID", dataset="fid", slug="assaults-schema-field-id") assaults_foi = ChartBlock(title="OCCURREDDATE", dataset="fod", slug="assaults-schema-field-officer-identifier") assaults_fst = ChartBlock(title="DIVISION", dataset="div", slug="assaults-schema-field-service-type") assaults_fft = ChartBlock(title="DISTRICT", dataset="dis", slug="assaults-schema-field-force-type") assaults_ffa = ChartBlock(title="SHIFT", dataset="shift", slug="assaults-schema-field-assignment") assaults_footer = ChartBlock(title="FOOTER", dataset="footer", slug="assaults-schema-footer") assaults_disclaimer = ChartBlock(title="DISCLAIMER", dataset="disclaimer", slug="assaults-schema-disclaimer") department.chart_blocks.append(assaults_intro) department.chart_blocks.append(assaults_fid) department.chart_blocks.append(assaults_foi) department.chart_blocks.append(assaults_fst) department.chart_blocks.append(assaults_fft) department.chart_blocks.append(assaults_ffa) department.chart_blocks.append(assaults_footer) department.chart_blocks.append(assaults_disclaimer) department.save() # verify that the blocks are returned in the expected structure assaults_blocks = department.get_assaults_schema_blocks() assert assaults_blocks['introduction'] == assaults_intro assert assaults_blocks['footer'] == assaults_footer assert assaults_blocks['disclaimer'] == assaults_disclaimer assert assaults_fid in assaults_blocks['blocks'] assert assaults_foi in assaults_blocks['blocks'] assert assaults_fst in assaults_blocks['blocks'] assert assaults_fft in assaults_blocks['blocks'] assert assaults_ffa in assaults_blocks['blocks']
def test_complaints_schema_edit_forms_exist(self, testapp): ''' Edit forms exist for the complaints schema page. ''' department = Department.create(name="B Police Department", short_name="BPD", load_defaults=True) # set up a user create_and_log_in_user(testapp, department) # make a request to specific front page response = testapp.get("/department/{}/edit/schema/complaints".format( department.id)) assert response.status_code == 200 # assert that the intro, footer, disclaimer forms are there assert 'editIntro' in response.forms assert 'editFooter' in response.forms assert 'editDisclaimer' in response.forms # assert that the field forms are there assert 'editIdTitleContentAndOrder' in response.forms assert 'editOccurredDateTitleContentAndOrder' in response.forms assert 'editDivisionTitleContentAndOrder' in response.forms assert 'editDistrictTitleContentAndOrder' in response.forms assert 'editShiftTitleContentAndOrder' in response.forms
def test_get_blocks_by_slugs_order(self): ''' We can get blocks sorted by order or in the order the slugs were passed. ''' department = Department.create(name="IM Police Department", short_name="IMPD", load_defaults=True) # get some complaint schema blocks blocks = department.get_complaint_schema_blocks()['blocks'] assert len(blocks) >= 6 blocks = blocks[:6] # make sure our test will be valid orders = [b.order for b in blocks] assert orders == sorted(orders) # make a list of slugs out of order ordered_slugs = [b.slug for b in blocks] mixedup_slugs = ordered_slugs.copy() mixedup_slugs = [ordered_slugs[i] for i in [5, 3, 1, 0, 2, 4]] assert ordered_slugs != mixedup_slugs # now request an ordered list of chart blocks from the mixed up list check_ordered_blocks = department.get_blocks_by_slugs(mixedup_slugs, sort_by_order=True) check_ordered_slugs = [b.slug for b in check_ordered_blocks] assert len(check_ordered_blocks) == 6 assert check_ordered_slugs == ordered_slugs assert check_ordered_slugs != mixedup_slugs # and request a list of chart blocks in the order the slugs are passed check_mixedup_blocks = department.get_blocks_by_slugs(mixedup_slugs, sort_by_order=False) check_mixedup_slugs = [b.slug for b in check_mixedup_blocks] assert len(check_mixedup_slugs) == 6 assert check_mixedup_slugs != ordered_slugs assert check_mixedup_slugs == mixedup_slugs
def test_get_pursuits_blocks(self): ''' Set and get pursuit chart blocks. ''' department = Department.create(name="SR Police Department", short_name="SRPD", load_defaults=False) # create & append chart blocks with the expected slugs pursuit_intro = ChartBlock(title="INTRO", dataset="intros", slug="pursuits-introduction") pursuit_bm = ChartBlock(title="BYMONTH", dataset="bymonth", slug="pursuits-by-month") pursuit_bt = ChartBlock(title="BYTEAM", dataset="byteam", slug="pursuits-by-team") pursuit_br = ChartBlock(title="BYREASON", dataset="byreason", slug="pursuits-by-reason") pursuit_bd = ChartBlock(title="BYDISTANCE", dataset="bydistance", slug="pursuits-by-distance") pursuit_bc = ChartBlock(title="BYCONCLUSION", dataset="byconclusion", slug="pursuits-by-conclusion") department.chart_blocks.append(pursuit_intro) department.chart_blocks.append(pursuit_bm) department.chart_blocks.append(pursuit_bt) department.chart_blocks.append(pursuit_br) department.chart_blocks.append(pursuit_bd) department.chart_blocks.append(pursuit_bc) department.save() # verify that the blocks are returned in the expected structure pursuit_blocks = department.get_pursuits_blocks() assert pursuit_blocks['introduction'] == pursuit_intro assert pursuit_blocks['first-block'] == pursuit_bm assert pursuit_blocks['blocks'][0] == pursuit_bt assert pursuit_blocks['blocks'][1] == pursuit_br assert pursuit_blocks['blocks'][2] == pursuit_bd assert pursuit_blocks['blocks'][3] == pursuit_bc
def test_assaults_schema_edit_forms_exist(self, testapp): ''' Edit forms exist for the complaints schema page. ''' department = Department.create(name="B Police Department", short_name="BPD", load_defaults=True) # set up a user create_and_log_in_user(testapp, department) # make a request to specific front page response = testapp.get("/department/{}/edit/schema/assaultsonofficers".format(department.id)) assert response.status_code == 200 # assert that the intro, footer, disclaimer forms are there assert 'editIntro' in response.forms assert 'editFooter' in response.forms assert 'editDisclaimer' in response.forms # assert that the field forms are there assert 'editIdTitleContentAndOrder' in response.forms assert 'editOfficerIdentifierTitleContentAndOrder' in response.forms assert 'editServiceTypeTitleContentAndOrder' in response.forms assert 'editForceTypeTitleContentAndOrder' in response.forms assert 'editAssignmentTitleContentAndOrder' in response.forms assert 'editArrestMadeTitleContentAndOrder' in response.forms assert 'editOfficerInjuredTitleContentAndOrder' in response.forms assert 'editReportFiledTitleContentAndOrder' in response.forms
def test_get_complaint_blocks(self): ''' Set and get complaint chart blocks. ''' department = Department.create(name="SR Police Department", short_name="SRPD", load_defaults=False) # create & append chart blocks with the expected slugs complaint_intro = ChartBlock(title="INTRO", dataset="", slug="complaints-introduction") complaint_bm = ChartBlock(title="BYMONTH", dataset="", slug="complaints-by-month") complaint_bal = ChartBlock(title="BYALLEGATION", dataset="", slug="complaints-by-allegation") complaint_bd = ChartBlock(title="BYDISPOSITION", dataset="", slug="complaints-by-disposition") complaint_bt = ChartBlock(title="BYTEAM", dataset="", slug="complaints-by-team") complaint_od = ChartBlock(title="OFFICERDEMOS", dataset="", slug="officer-demographics") department.chart_blocks.append(complaint_intro) department.chart_blocks.append(complaint_bm) department.chart_blocks.append(complaint_bal) department.chart_blocks.append(complaint_bd) department.chart_blocks.append(complaint_bt) department.chart_blocks.append(complaint_od) department.save() # verify that the blocks are returned in the expected structure complaint_blocks = department.get_complaint_blocks() assert complaint_blocks['introduction'] == complaint_intro assert complaint_blocks['first-block'] == complaint_bm assert complaint_blocks['blocks'][0] == complaint_bal assert complaint_blocks['blocks'][1] == complaint_bd assert complaint_blocks['blocks'][2] == complaint_bt assert complaint_blocks['blocks'][3] == complaint_od
def test_changing_schema_field_order_reorders_other_fields(self, testapp): ''' Changing the order value of a schema field will re-order the other fields to make room. ''' department = Department.create(name="B Police Department", short_name="BPD", load_defaults=True) # set up a user create_and_log_in_user(testapp, department) for incident_type in [("complaints", "complaints"), ("assaults", "assaultsonofficers"), ("ois", "ois"), ("uof", "useofforce")]: # make a request to specific front page response = testapp.get("/department/{}/edit/schema/{}".format(department.id, incident_type[1])) assert response.status_code == 200 schema_field_prefix = "{}-schema-field-".format(incident_type[0]) schema_fields = department.get_blocks_by_slug_startswith(schema_field_prefix) assert schema_fields[0].order < schema_fields[1].order assert schema_fields[1].order < schema_fields[2].order assert schema_fields[2].order < schema_fields[3].order form_name = "edit{}TitleContentAndOrder".format(schema_fields[2].slug.replace(schema_field_prefix, "").replace("-", " ").title().replace(" ", "")) assert form_name in response.forms form = response.forms[form_name] new_order = schema_fields[0].order form['chart_order'] = new_order response = form.submit().follow() assert response.status_code == 200 check_fields = department.get_blocks_by_slug_startswith(schema_field_prefix) assert check_fields[0].order < check_fields[1].order assert check_fields[1].order < check_fields[2].order assert check_fields[2].order < check_fields[3].order
def test_submit_non_numeric_value_to_order(self, testapp): ''' Submitting the form to change the order of a schmea field with a non-numeric value doesn't change anything. ''' department = Department.create(name="B Police Department", short_name="BPD", load_defaults=True) # set up a user create_and_log_in_user(testapp, department) # get the order of a schema field check_order = ChartBlock.query.filter_by( slug="complaints-schema-field-shift", department_id=department.id).first().order # make a request to specific front page response = testapp.get("/department/{}/edit/schema/complaints".format( department.id)) assert response.status_code == 200 assert 'editShiftTitleContentAndOrder' in response.forms form = response.forms['editShiftTitleContentAndOrder'] new_order = "I'm not a number" form['chart_order'] = new_order response = form.submit().follow() assert response.status_code == 200 checkblock = ChartBlock.query.filter_by( slug="complaints-schema-field-shift", department_id=department.id).first() assert checkblock.order == check_order
def test_get_complaint_schema_blocks(self): ''' Set and get complaint schema chart blocks. ''' department = Department.create(name="IM Police Department", short_name="IMPD", load_defaults=False) # create & append chart blocks with the expected slugs complaint_intro = ChartBlock(title="INTRO", dataset="intros", slug="complaints-schema-introduction") complaint_id = ChartBlock(title="FIELDID", dataset="fid", slug="complaints-schema-field-id") complaint_od = ChartBlock(title="OCCURREDDATE", dataset="fod", slug="complaints-schema-field-occurred-date") complaint_div = ChartBlock(title="DIVISION", dataset="div", slug="complaints-schema-field-division") complaint_dis = ChartBlock(title="DISTRICT", dataset="dis", slug="complaints-schema-field-district") complaint_shift = ChartBlock(title="SHIFT", dataset="shift", slug="complaints-schema-field-shift") complaint_footer = ChartBlock(title="FOOTER", dataset="footer", slug="complaints-schema-footer") complaint_disclaimer = ChartBlock(title="DISCLAIMER", dataset="disclaimer", slug="complaints-schema-disclaimer") department.chart_blocks.append(complaint_intro) department.chart_blocks.append(complaint_id) department.chart_blocks.append(complaint_od) department.chart_blocks.append(complaint_div) department.chart_blocks.append(complaint_dis) department.chart_blocks.append(complaint_shift) department.chart_blocks.append(complaint_footer) department.chart_blocks.append(complaint_disclaimer) department.save() # verify that the blocks are returned in the expected structure complaint_blocks = department.get_complaint_schema_blocks() assert complaint_blocks['introduction'] == complaint_intro assert complaint_blocks['footer'] == complaint_footer assert complaint_blocks['disclaimer'] == complaint_disclaimer assert complaint_id in complaint_blocks['blocks'] assert complaint_od in complaint_blocks['blocks'] assert complaint_div in complaint_blocks['blocks'] assert complaint_dis in complaint_blocks['blocks'] assert complaint_shift in complaint_blocks['blocks']
def test_dataset_is_public_and_has_data(self): ''' We can accurately tell if a dataset is public and has data. ''' # create a department department = Department.create(name="B Police Department", short_name="BPD", load_defaults=True) # none of the datasets have data, so they should all return false assert department.dataset_is_public_and_has_data("complaints") == False assert department.dataset_is_public_and_has_data("uof") == False assert department.dataset_is_public_and_has_data("ois") == False assert department.dataset_is_public_and_has_data("assaults") == False # create incidents and verify that the datasets are now displayable CitizenComplaintBPD.create(department_id=department.id, opaque_id="12345abcde") assert department.dataset_is_public_and_has_data("complaints") == True UseOfForceIncidentBPD.create(department_id=department.id, opaque_id="23456bcdef") assert department.dataset_is_public_and_has_data("uof") == True OfficerInvolvedShootingBPD.create(department_id=department.id, opaque_id="34567cdefg") assert department.dataset_is_public_and_has_data("ois") == True # now make them all not public, and they should be false again department.is_public_citizen_complaints = False assert department.dataset_is_public_and_has_data("complaints") == False department.is_public_use_of_force_incidents = False assert department.dataset_is_public_and_has_data("uof") == False department.is_public_officer_involved_shootings = False assert department.dataset_is_public_and_has_data("ois") == False
def test_extractor_post_triggers_slack_notification(self, testapp): ''' A valid heartbeat post triggers a Slack notification ''' # set up the extractor department = Department.create(name="Good Police Department", short_name="GPD", load_defaults=False) Extractor.create(username='******', email='*****@*****.**', password="******", department_id=department.id, next_month=10, next_year=2006) # set the correct authorization testapp.authorization = ('Basic', ('extractor', 'password')) # set a fake Slack webhook URL fake_webhook_url = 'http://webhook.example.com/' current_app.config['SLACK_WEBHOOK_URL'] = fake_webhook_url # create a mock to receive POST requests to that URL responses.add(responses.POST, fake_webhook_url, status=200) # post a sample json object to the heartbeat URL testapp.post_json("/data/heartbeat", params={"heartbeat": "heartbeat"}) # test the captured post payload post_body = json.loads(responses.calls[0].request.body) assert 'Comport Pinged by Extractor!' in post_body['text'] # delete the fake Slack webhook URL del(current_app.config['SLACK_WEBHOOK_URL']) # reset the mock responses.reset()
def test_edit_and_preview_links_on_department_admin_page(sefl, testapp): ''' There are links to preview & edit main and schema pages from the department admin page. ''' department = Department.create(name="B Police Department", short_name="BPD", load_defaults=True) # set up a user create_and_log_in_user(testapp, department) # make a request to specific front page response = testapp.get("/department/{}".format(department.id)) assert response.status_code == 200 soup = BeautifulSoup(response.text, "html.parser") assert soup.find("a", href="{}/preview/useofforce".format(department.id)) is not None assert soup.find("a", href="{}/preview/complaints".format(department.id)) is not None assert soup.find("a", href="{}/preview/ois".format(department.id)) is not None assert soup.find("a", href="{}/preview/pursuits".format(department.id)) is not None assert soup.find("a", href="{}/preview/assaultsonofficers".format(department.id)) is not None assert soup.find("a", href="{}/edit/useofforce".format(department.id)) is not None assert soup.find("a", href="{}/edit/complaints".format(department.id)) is not None assert soup.find("a", href="{}/edit/ois".format(department.id)) is not None assert soup.find("a", href="{}/edit/pursuits".format(department.id)) is not None assert soup.find("a", href="{}/edit/assaultsonofficers".format(department.id)) is not None assert soup.find("a", href="{}/preview/schema/useofforce".format(department.id)) is not None assert soup.find("a", href="{}/preview/schema/complaints".format(department.id)) is not None assert soup.find("a", href="{}/preview/schema/ois".format(department.id)) is not None assert soup.find("a", href="{}/preview/schema/pursuits".format(department.id)) is not None assert soup.find("a", href="{}/preview/schema/assaultsonofficers".format(department.id)) is not None assert soup.find("a", href="{}/edit/schema/useofforce".format(department.id)) is not None assert soup.find("a", href="{}/edit/schema/complaints".format(department.id)) is not None assert soup.find("a", href="{}/edit/schema/ois".format(department.id)) is not None assert soup.find("a", href="{}/edit/schema/pursuits".format(department.id)) is not None assert soup.find("a", href="{}/edit/schema/assaultsonofficers".format(department.id)) is not None
def test_get_uof_blocks(self): ''' Set and get uof chart blocks. ''' department = Department.create(name="W Police Department", short_name="WPD", load_defaults=False) # create & append chart blocks with the expected slugs uof_intro = ChartBlock(title="INTRO", dataset="intros", slug="uof-introduction") uof_ft = ChartBlock(title="FORCETYPE", dataset="forcetype", slug="uof-force-type") uof_bid = ChartBlock(title="BYASSIGNMENT", dataset="bid", slug="uof-by-inc-district") uof_od = ChartBlock(title="OFFICERDEMOS", dataset="od", slug="officer-demographics") uof_race = ChartBlock(title="RACE", dataset="race", slug="uof-race") department.chart_blocks.append(uof_intro) department.chart_blocks.append(uof_ft) department.chart_blocks.append(uof_bid) department.chart_blocks.append(uof_od) department.chart_blocks.append(uof_race) department.save() # verify that the blocks are returned in the expected structure uof_blocks = department.get_uof_blocks() assert uof_blocks['introduction'] == uof_intro assert uof_blocks['first-block'] == uof_ft assert uof_blocks['blocks'][0] == uof_bid assert uof_blocks['blocks'][1] == uof_od assert uof_blocks['blocks'][2] == uof_race
def test_dataset_is_public_and_has_data(self): ''' We can accurately tell if a dataset is public and has data. ''' # create a department department = Department.create(name="W Police Department", short_name="WPD", load_defaults=True) # none of the datasets have data, so they should all return false assert department.dataset_is_public_and_has_data("complaints") == False assert department.dataset_is_public_and_has_data("uof") == False # the total count should be zero assert department.displayable_dataset_count() == 0 # create incidents and verify that the datasets are now displayable CitizenComplaintWPD.create(department_id=department.id, opaque_id="12345abcde") assert department.dataset_is_public_and_has_data("complaints") == True assert department.displayable_dataset_count() == 1 UseOfForceIncidentWPD.create(department_id=department.id, opaque_id="23456bcdef") assert department.dataset_is_public_and_has_data("uof") == True assert department.displayable_dataset_count() == 2 # now make them all not public, and they should be false again department.is_public_citizen_complaints = False assert department.dataset_is_public_and_has_data("complaints") == False department.is_public_use_of_force_incidents = False assert department.dataset_is_public_and_has_data("uof") == False assert department.displayable_dataset_count() == 0
def test_get_complaint_blocks(self): ''' Set and get complaint chart blocks. ''' department = Department.create(name="B Police Department", short_name="BPD", load_defaults=False) # create & append chart blocks with the expected slugs complaint_intro = ChartBlock(title="INTRO", dataset="intros", slug="complaints-introduction") complaint_bm = ChartBlock(title="BYMONTH", dataset="bymonth", slug="complaints-by-month") complaint_bya = ChartBlock(title="BYALLEGATION", dataset="bya", slug="complaints-by-allegation") complaint_bdis = ChartBlock(title="BYDISPOSITION", dataset="bdis", slug="complaints-by-disposition") complaint_bass = ChartBlock(title="BYPRECINCT", dataset="bpre", slug="complaints-by-assignment") complaint_od = ChartBlock(title="OFFICERDEMOS", dataset="od", slug="officer-demographics") complaint_bde = ChartBlock(title="BYDEMO", dataset="bde", slug="complaints-by-demographic") complaint_bof = ChartBlock(title="BYOFFICER", dataset="bof", slug="complaints-by-officer-with-cap") department.chart_blocks.append(complaint_intro) department.chart_blocks.append(complaint_bm) department.chart_blocks.append(complaint_bya) department.chart_blocks.append(complaint_bdis) department.chart_blocks.append(complaint_bass) department.chart_blocks.append(complaint_od) department.chart_blocks.append(complaint_bde) department.chart_blocks.append(complaint_bof) department.save() # verify that the blocks are returned in the expected structure complaint_blocks = department.get_complaint_blocks() assert complaint_blocks['introduction'] == complaint_intro assert complaint_blocks['first-block'] == complaint_bm assert complaint_blocks['blocks'][0] == complaint_bya assert complaint_blocks['blocks'][1] == complaint_bdis assert complaint_blocks['blocks'][2] == complaint_bass assert complaint_blocks['blocks'][3] == complaint_od assert complaint_blocks['blocks'][4] == complaint_bde assert complaint_blocks['blocks'][5] == complaint_bof
def test_get_ois_blocks(self): ''' Set and get ois chart blocks. ''' department = Department.create(name="SR Police Department", short_name="SRPD", load_defaults=False) # create & append chart blocks with the expected slugs ois_intro = ChartBlock(title="INTRO", dataset="intros", slug="ois-introduction") ois_bm = ChartBlock(title="BYMONTH", dataset="bm", slug="ois-by-month") ois_by = ChartBlock(title="BYTYPE", dataset="bytype", slug="ois-by-type") ois_bt = ChartBlock(title="BYTEAM", dataset="byteam", slug="ois-by-team") ois_od = ChartBlock(title="OFFICERDEMOS", dataset="od", slug="officer-demographics") department.chart_blocks.append(ois_intro) department.chart_blocks.append(ois_bm) department.chart_blocks.append(ois_by) department.chart_blocks.append(ois_bt) department.chart_blocks.append(ois_od) department.save() # verify that the blocks are returned in the expected structure ois_blocks = department.get_ois_blocks() assert ois_blocks['introduction'] == ois_intro assert ois_blocks['first-block'] == ois_bm assert ois_blocks['blocks'][0] == ois_by assert ois_blocks['blocks'][1] == ois_bt assert ois_blocks['blocks'][2] == ois_od
def test_editing_useofforce_schema_field_value(self, testapp): ''' Submitting the form to edit a schema field changes the correct value in the database ''' department = Department.create(name="B Police Department", short_name="BPD", load_defaults=True) # set up a user create_and_log_in_user(testapp, department) # make a request to specific front page response = testapp.get("/department/{}/edit/schema/useofforce".format(department.id)) assert response.status_code == 200 assert 'editShiftTitleContentAndOrder' in response.forms form = response.forms['editShiftTitleContentAndOrder'] new_title = "A New Data Field Title" new_content = "A Short Definition of this Data Field" new_order = 99 form['chart_title'] = new_title form['chart_content'] = new_content form['chart_order'] = new_order response = form.submit().follow() assert response.status_code == 200 checkblock = ChartBlock.query.filter_by(slug="uof-schema-field-shift").first() assert checkblock.title == new_title assert checkblock.content == new_content assert checkblock.order == len(department.get_blocks_by_slug_startswith("uof-schema-field-")) - 1
def test_get_uof_blocks(self): ''' Set and get uof chart blocks. ''' department = Department.create(name="IM Police Department", short_name="IMPD", load_defaults=False) # create & append chart blocks with the expected slugs uof_intro = ChartBlock(title="INTRO", dataset="intros", slug="uof-introduction") uof_ft = ChartBlock(title="FORCETYPE", dataset="forcetype", slug="uof-force-type") uof_bid = ChartBlock(title="BYASSIGNMENT", dataset="bid", slug="uof-by-inc-district") uof_od = ChartBlock(title="OFFICERDEMOS", dataset="od", slug="officer-demographics") uof_race = ChartBlock(title="RACE", dataset="race", slug="uof-race") department.chart_blocks.append(uof_intro) department.chart_blocks.append(uof_ft) department.chart_blocks.append(uof_bid) department.chart_blocks.append(uof_od) department.chart_blocks.append(uof_race) department.save() # verify that the blocks are returned in the expected structure uof_blocks = department.get_uof_blocks() assert uof_blocks['introduction'] == uof_intro assert uof_blocks['first-block'] == uof_ft assert uof_blocks['blocks'][0] == uof_bid assert uof_blocks['blocks'][1] == uof_od assert uof_blocks['blocks'][2] == uof_race
def test_get_ois_blocks(self): ''' Set and get ois chart blocks. ''' department = Department.create(name="IM Police Department", short_name="IMPD", load_defaults=False) # create & append chart blocks with the expected slugs ois_intro = ChartBlock(title="INTRO", dataset="intros", slug="ois-introduction") ois_bid = ChartBlock(title="BYASSIGNMENT", dataset="bid", slug="ois-by-inc-district") ois_wt = ChartBlock(title="WEAPONTYPE", dataset="weapontype", slug="ois-weapon-type") ois_od = ChartBlock(title="OFFICERDEMOS", dataset="od", slug="officer-demographics") ois_race = ChartBlock(title="RACE", dataset="race", slug="ois-race") department.chart_blocks.append(ois_intro) department.chart_blocks.append(ois_bid) department.chart_blocks.append(ois_wt) department.chart_blocks.append(ois_od) department.chart_blocks.append(ois_race) department.save() # verify that the blocks are returned in the expected structure ois_blocks = department.get_ois_blocks() assert ois_blocks['introduction'] == ois_intro assert ois_blocks['first-block'] == ois_bid assert ois_blocks['blocks'][0] == ois_wt assert ois_blocks['blocks'][1] == ois_od assert ois_blocks['blocks'][2] == ois_race
def test_submitting_schema_intro_field_value(self, testapp): ''' Submitting the form to edit a schema intro field changes the expected value in the database and not others ''' department = Department.create(name="B Police Department", short_name="BPD", load_defaults=True) # set up a user create_and_log_in_user(testapp, department) # make a request to specific front page response = testapp.get("/department/{}/edit/schema/complaints".format(department.id)) assert response.status_code == 200 assert 'editIntro' in response.forms form = response.forms['editIntro'] new_content = "A Short Definition of this Data Field" form['chart_content'] = new_content checkblock = ChartBlock.query.filter_by(slug="complaints-schema-introduction", department_id=department.id).first() title = checkblock.title order = checkblock.order response = form.submit().follow() assert response.status_code == 200 checkblock2 = ChartBlock.query.filter_by(slug="complaints-schema-introduction", department_id=department.id).first() assert checkblock.content == new_content assert title == checkblock2.title assert order == checkblock2.order
def test_can_set_extractor_start_date(self, testapp): ''' Can set an extraction start date. ''' # set up the department department = Department.create(name="Good Police Department", short_name="GPD", load_defaults=False) # set up a user user = User.create(username="******", email="*****@*****.**", password="******") user.departments.append(department) user.active = True user.save() # login response = testapp.get("/login/") form = response.forms['loginForm'] form['username'] = user.username form['password'] = '******' response = form.submit().follow() # create an extractor account extractor_password = "******" extractor, _ = Extractor.from_department_and_password(department=department, password=extractor_password) # submit the extractor start date form response = testapp.get("/department/{}".format(department.id)) form = response.forms["extractionStartForm"] submit_month = 10 submit_year = 2006 form['month'] = str(submit_month) form['year'] = str(submit_year) response = form.submit('submit').follow() # the new date was set assert extractor.next_month == submit_month assert extractor.next_year == submit_year
def test_schema_chart_block_order(self): ''' Set and get complaint chart blocks. ''' department = Department.create(name="IM Police Department", short_name="IMPD", load_defaults=True) # get complaint schema blocks before_blocks = department.get_complaint_schema_blocks() # make sure our test will be valid assert len(before_blocks['blocks']) > 2 assert before_blocks['blocks'][0].order < before_blocks['blocks'][ 1].order assert before_blocks['blocks'][1].order < 100 assert before_blocks['blocks'][-1].order < 100 # change the order of the first block to 100 block = before_blocks['blocks'][0] block.order = 100 block.save() # get the blocks again and test the order after_blocks = department.get_complaint_schema_blocks() assert before_blocks['blocks'][1].order == after_blocks['blocks'][ 0].order assert before_blocks['blocks'][1].slug == after_blocks['blocks'][ 0].slug assert after_blocks['blocks'][-1].order == 100 assert before_blocks['blocks'][0].slug == after_blocks['blocks'][ -1].slug
def test_submitting_schema_edit_form_redirects_to_preview(self, testapp): ''' Submitting the form to edit a schema field changes the correct value in the database ''' department = Department.create(name="B Police Department", short_name="BPD", load_defaults=True) # set up a user create_and_log_in_user(testapp, department) # make a request to specific front page response = testapp.get("/department/{}/edit/schema/complaints".format(department.id)) assert response.status_code == 200 # submit new title & content assert 'editShiftTitleContentAndOrder' in response.forms form = response.forms['editShiftTitleContentAndOrder'] new_title = "A New Data Field Title" new_content = "A Short Definition of this Data Field" new_order = 99 form['chart_title'] = new_title form['chart_content'] = new_content form['chart_order'] = new_order response = form.submit() # the response should be a redirect assert response.status_code == 302 # the location of the redirect should be the preview page parsed = urlparse(response.location) assert parsed.path == "/department/{}/preview/schema/complaints".format(department.id)
def test_can_set_extractor_start_date(self, testapp): ''' Can set an extraction start date. ''' # set up the department department = Department.create(name="IM Police Department", short_name="IMPD", load_defaults=False) # set up a user user = User.create(username="******", email="*****@*****.**", password="******") user.departments.append(department) user.active = True user.save() # login response = testapp.get("/login/") form = response.forms['loginForm'] form['username'] = user.username form['password'] = '******' response = form.submit().follow() # create an extractor account extractor_password = "******" extractor, _ = Extractor.from_department_and_password(department=department, password=extractor_password) # submit the extractor start date form response = testapp.get("/department/{}".format(department.id)) form = response.forms["extractionStartForm"] submit_month = 10 submit_year = 2006 form['month'] = str(submit_month) form['year'] = str(submit_year) response = form.submit('submit').follow() # the new date was set assert extractor.next_month == submit_month assert extractor.next_year == submit_year
def test_dataset_is_public_and_has_data(self): ''' We can accurately tell if a dataset is public and has data. ''' # create a department department = Department.create(name="B Police Department", short_name="BPD", load_defaults=True) # none of the datasets have data, so they should all return false assert department.dataset_is_public_and_has_data("complaints") == False assert department.dataset_is_public_and_has_data("uof") == False assert department.dataset_is_public_and_has_data("ois") == False assert department.dataset_is_public_and_has_data("assaults") == False # the total count should be zero assert department.displayable_dataset_count() == 0 # create incidents and verify that the datasets are now displayable CitizenComplaintBPD.create(department_id=department.id, opaque_id="12345abcde") assert department.dataset_is_public_and_has_data("complaints") == True assert department.displayable_dataset_count() == 1 UseOfForceIncidentBPD.create(department_id=department.id, opaque_id="23456bcdef") assert department.dataset_is_public_and_has_data("uof") == True assert department.displayable_dataset_count() == 2 OfficerInvolvedShootingBPD.create(department_id=department.id, opaque_id="34567cdefg") assert department.dataset_is_public_and_has_data("ois") == True assert department.displayable_dataset_count() == 3 # now make them all not public, and they should be false again department.is_public_citizen_complaints = False assert department.dataset_is_public_and_has_data("complaints") == False department.is_public_use_of_force_incidents = False assert department.dataset_is_public_and_has_data("uof") == False department.is_public_officer_involved_shootings = False assert department.dataset_is_public_and_has_data("ois") == False assert department.displayable_dataset_count() == 0
def test_assaults_schema_edit_forms_exist(self, testapp): ''' Edit forms exist for the complaints schema page. ''' department = Department.create(name="B Police Department", short_name="BPD", load_defaults=True) # set up a user create_and_log_in_user(testapp, department) # make a request to specific front page response = testapp.get("/department/{}/edit/schema/assaultsonofficers".format(department.id)) assert response.status_code == 200 # assert that the intro, footer, disclaimer forms are there assert 'editIntro' in response.forms assert 'editFooter' in response.forms assert 'editDisclaimer' in response.forms # assert that the field forms are there assert 'editIdTitleContentAndOrder' in response.forms assert 'editOfficerIdentifierTitleContentAndOrder' in response.forms assert 'editServiceTypeTitleContentAndOrder' in response.forms assert 'editForceTypeTitleContentAndOrder' in response.forms assert 'editAssignmentTitleContentAndOrder' in response.forms assert 'editArrestMadeTitleContentAndOrder' in response.forms assert 'editOfficerInjuredTitleContentAndOrder' in response.forms assert 'editReportFiledTitleContentAndOrder' in response.forms
def test_get_assaults_schema_blocks(self): ''' Set and get assaults schema chart blocks. ''' department = Department.create(name="IM Police Department", short_name="IMPD", load_defaults=False) # create & append chart blocks with the expected slugs assaults_intro = ChartBlock(title="INTRO", dataset="intros", slug="assaults-schema-introduction") assaults_fid = ChartBlock(title="FIELDID", dataset="fid", slug="assaults-schema-field-id") assaults_foi = ChartBlock(title="OCCURREDDATE", dataset="fod", slug="assaults-schema-field-officer-identifier") assaults_fst = ChartBlock(title="DIVISION", dataset="div", slug="assaults-schema-field-service-type") assaults_fft = ChartBlock(title="DISTRICT", dataset="dis", slug="assaults-schema-field-force-type") assaults_ffa = ChartBlock(title="SHIFT", dataset="shift", slug="assaults-schema-field-assignment") assaults_footer = ChartBlock(title="FOOTER", dataset="footer", slug="assaults-schema-footer") assaults_disclaimer = ChartBlock(title="DISCLAIMER", dataset="disclaimer", slug="assaults-schema-disclaimer") department.chart_blocks.append(assaults_intro) department.chart_blocks.append(assaults_fid) department.chart_blocks.append(assaults_foi) department.chart_blocks.append(assaults_fst) department.chart_blocks.append(assaults_fft) department.chart_blocks.append(assaults_ffa) department.chart_blocks.append(assaults_footer) department.chart_blocks.append(assaults_disclaimer) department.save() # verify that the blocks are returned in the expected structure assaults_blocks = department.get_assaults_schema_blocks() assert assaults_blocks['introduction'] == assaults_intro assert assaults_blocks['footer'] == assaults_footer assert assaults_blocks['disclaimer'] == assaults_disclaimer assert assaults_fid in assaults_blocks['blocks'] assert assaults_foi in assaults_blocks['blocks'] assert assaults_fst in assaults_blocks['blocks'] assert assaults_fft in assaults_blocks['blocks'] assert assaults_ffa in assaults_blocks['blocks']
def test_changing_schema_field_order_reorders_other_fields(self, testapp): ''' Changing the order value of a schema field will re-order the other fields to make room. ''' department = Department.create(name="B Police Department", short_name="BPD", load_defaults=True) # set up a user create_and_log_in_user(testapp, department) for incident_type in [("complaints", "complaints"), ("assaults", "assaultsonofficers"), ("ois", "ois"), ("uof", "useofforce"), ("pursuits", "pursuits")]: # make a request to specific front page response = testapp.get("/department/{}/edit/schema/{}".format(department.id, incident_type[1])) assert response.status_code == 200 schema_field_prefix = "{}-schema-field-".format(incident_type[0]) schema_fields = department.get_blocks_by_slug_startswith(schema_field_prefix) assert schema_fields[0].order < schema_fields[1].order assert schema_fields[1].order < schema_fields[2].order assert schema_fields[2].order < schema_fields[3].order form_name = "edit{}TitleContentAndOrder".format(schema_fields[2].slug.replace(schema_field_prefix, "").replace("-", " ").title().replace(" ", "")) assert form_name in response.forms form = response.forms[form_name] new_order = schema_fields[0].order form['chart_order'] = new_order response = form.submit().follow() assert response.status_code == 200 check_fields = department.get_blocks_by_slug_startswith(schema_field_prefix) assert check_fields[0].order < check_fields[1].order assert check_fields[1].order < check_fields[2].order assert check_fields[2].order < check_fields[3].order
def test_get_complaint_schema_blocks(self): ''' Set and get complaint schema chart blocks. ''' department = Department.create(name="IM Police Department", short_name="IMPD", load_defaults=False) # create & append chart blocks with the expected slugs complaint_intro = ChartBlock(title="INTRO", dataset="intros", slug="complaints-schema-introduction") complaint_id = ChartBlock(title="FIELDID", dataset="fid", slug="complaints-schema-field-id") complaint_od = ChartBlock(title="OCCURREDDATE", dataset="fod", slug="complaints-schema-field-occurred-date") complaint_div = ChartBlock(title="DIVISION", dataset="div", slug="complaints-schema-field-division") complaint_dis = ChartBlock(title="DISTRICT", dataset="dis", slug="complaints-schema-field-district") complaint_shift = ChartBlock(title="SHIFT", dataset="shift", slug="complaints-schema-field-shift") complaint_footer = ChartBlock(title="FOOTER", dataset="footer", slug="complaints-schema-footer") complaint_disclaimer = ChartBlock(title="DISCLAIMER", dataset="disclaimer", slug="complaints-schema-disclaimer") department.chart_blocks.append(complaint_intro) department.chart_blocks.append(complaint_id) department.chart_blocks.append(complaint_od) department.chart_blocks.append(complaint_div) department.chart_blocks.append(complaint_dis) department.chart_blocks.append(complaint_shift) department.chart_blocks.append(complaint_footer) department.chart_blocks.append(complaint_disclaimer) department.save() # verify that the blocks are returned in the expected structure complaint_blocks = department.get_complaint_schema_blocks() assert complaint_blocks['introduction'] == complaint_intro assert complaint_blocks['footer'] == complaint_footer assert complaint_blocks['disclaimer'] == complaint_disclaimer assert complaint_id in complaint_blocks['blocks'] assert complaint_od in complaint_blocks['blocks'] assert complaint_div in complaint_blocks['blocks'] assert complaint_dis in complaint_blocks['blocks'] assert complaint_shift in complaint_blocks['blocks']
def test_validate_invite_code_used_already(self, user): department = Department.create(name="dept", short_name="DPD", load_defaults=False) Invite_Code.create(department_id=department.id, code="code1", used=True) form = RegisterForm(username='******', email='*****@*****.**', password='******', confirm='example', invite_code="code1") assert form.validate() is False assert 'Invite Code has already been used.' in form.invite_code.errors
def test_assaults_schema_page_exists(self, testapp): # get a department from the fixture department = Department.create(name="B Police Department", short_name="BPD", load_defaults=True) # make a request to specific front page response = testapp.get("/department/{}/schema/assaultsonofficers/".format(department.short_name)) assert response.status_code == 200
def test_assaults_csv_endpoint_exists(self, testapp): # create a department department = Department.create(name="IM Police Department", short_name="IMPD", load_defaults=False) # make a request to specific front page response = testapp.get("/department/{}/assaultsonofficers.csv".format(department.id)) assert response.status_code == 200
def test_valid_login_replies_with_request(self, testapp): right_department = Department.create(name="good2", load_defaults=False) Extractor.create(username="******", email="*****@*****.**", password="******", department_id=right_department.id) testapp.authorization = ("Basic", ("good4", "valid")) res = testapp.post_json("/data/heartbeat", params={"json": "yep"}, expect_errors=True) assert res.status_code == 200
def test_post_mistyped_uof_data(self, testapp): ''' New UOF data from the extractor is processed as expected. ''' # Set up the extractor department = Department.create(name="Good Police Department", short_name="GPD", load_defaults=False) extractor, envs = Extractor.from_department_and_password(department=department, password="******") # Set the correct authorization testapp.authorization = ('Basic', (extractor.username, 'password')) # Get a generated list of UOF descriptions from the JSON test client test_client = JSONTestClient() uof_count = 1 uof_data = test_client.get_prebaked_uof(last=uof_count) # The app expects number values to be transmitted as strings. Let's change them to integers. uof_data[0]['residentAge'] = 28 uof_data[0]['officerAge'] = 46 uof_data[0]['officerYearsOfService'] = 17 # post the json to the UOF URL response = testapp.post_json("/data/UOF", params={'month': 0, 'year': 0, 'data': uof_data}) # assert that we got the expected reponse assert response.status_code == 200 assert response.json_body['updated'] == 0 assert response.json_body['added'] == uof_count # check the uof incident in the database against the data that was sent cleaner = Cleaners() sent_uof = uof_data[0] check_uof = UseOfForceIncident.query.filter_by(opaque_id=sent_uof['opaqueId']).first() assert check_uof.occured_date.strftime('%Y-%m-%d %-H:%-M:%S') == sent_uof['occuredDate'] assert check_uof.division == cleaner.capitalize(sent_uof['division']) assert check_uof.precinct == cleaner.capitalize(sent_uof['precinct']) assert check_uof.shift == cleaner.capitalize(sent_uof['shift']) assert check_uof.beat == cleaner.capitalize(sent_uof['beat']) assert check_uof.disposition == sent_uof['disposition'] assert check_uof.officer_force_type == cleaner.officer_force_type(sent_uof['officerForceType']) assert check_uof.use_of_force_reason == sent_uof['useOfForceReason'] assert check_uof.service_type == sent_uof['serviceType'] assert check_uof.arrest_made == sent_uof['arrestMade'] assert check_uof.arrest_charges == sent_uof['arrestCharges'] assert check_uof.resident_weapon_used == sent_uof['residentWeaponUsed'] assert check_uof.resident_injured == sent_uof['residentInjured'] assert check_uof.resident_hospitalized == sent_uof['residentHospitalized'] assert check_uof.officer_injured == sent_uof['officerInjured'] assert check_uof.officer_hospitalized == sent_uof['officerHospitalized'] assert check_uof.resident_race == cleaner.race(sent_uof['residentRace']) assert check_uof.resident_sex == cleaner.sex(sent_uof['residentSex']) assert check_uof.resident_age == cleaner.number_to_string(sent_uof['residentAge']) assert check_uof.resident_condition == sent_uof['residentCondition'] assert check_uof.officer_identifier == sent_uof['officerIdentifier'] assert check_uof.officer_race == cleaner.race(sent_uof['officerRace']) assert check_uof.officer_sex == cleaner.sex(sent_uof['officerSex']) assert check_uof.officer_age == cleaner.number_to_string(sent_uof['officerAge']) assert check_uof.officer_years_of_service == cleaner.number_to_string(sent_uof['officerYearsOfService']) assert check_uof.officer_condition == sent_uof['officerCondition']
def test_department_access(self, user, testapp): department = Department.create(name="Busy Town Public Safety", short_name="BTPD", load_defaults=False) user.departments.append(department) user.save() TestLoggingIn.test_can_log_in_returns_200(self, user=user, testapp=testapp) res = testapp.get("/department/6").follow() assert res.status_code == 200 assert "You do not have sufficient permissions to do that" in res