def test_change_api_key(auth_user, auth_client, client, mailoutbox): # Check/store original API key as visible to user original_token = auth_user.get_api_key() response = auth_client.get(reverse('user-details')) check_response(response) content = re.sub(r'\s+', ' ', response.content.decode()).strip() assert original_token in content # Make sure warning/confirmation template is rendered on get request response = auth_client.get(reverse('reset-api-key')) check_response(response) content = re.sub(r'\s+', ' ', response.content.decode()).strip() assert "This change takes place immediately and cannot be undone." in content # Change API key through web request response = auth_client.post(reverse('reset-api-key')) assert response.status_code == 302 assert response.url.endswith('/user/details') # Make sure new API key is in place and immediately visible to user auth_user.refresh_from_db() response = auth_client.get(reverse('user-details')) check_response(response) content = re.sub(r'\s+', ' ', response.content.decode()).strip() assert auth_user.get_api_key() in content assert original_token not in content # Make sure mail is sent and contains the correct new and old API keys message = mailoutbox[0].body assert "Your Case.law API key reset is complete" in message # Make sure auth is in place unauth_response = client.post(reverse('reset-api-key')) assert unauth_response.status_code == 302 assert "/user/login/" in unauth_response.url
def test_timeline_update(client, auth_client): tl = Timeline.objects.create(created_by=auth_client.auth_user, timeline=timeline) response = auth_client.get(retrieve_url + str(tl.id)) check_response(response, content_type="application/json") assert response.json()["timeline"]["title"] == timeline["title"] new_title = "My second timeline attempt" timeline["title"] = new_title update_url = reverse('labs:chronolawgic-api-update', args=[str(tl.id)]) response = auth_client.post(update_url, {"timeline": timeline}, format='json') check_response(response, content_type="application/json") assert response.json()["timeline"]["title"] == new_title new_title = "My third timeline attempt" timeline["title"] = new_title update_url = reverse('labs:chronolawgic-api-update', args=[str(tl.id)]) # don't allow unauthenticated users response = client.post(update_url, {"timeline": timeline}, format='json') check_response(response, status_code=403, content_type="application/json") response = auth_client.get(retrieve_url + str(tl.id)) assert response.json()["timeline"]["title"] != timeline["title"]
def test_case_citation_redirect(client, case_factory, elasticsearch): """Should allow various forms of citation, should redirect to normalized_cite""" case = case_factory(citations__cite='123 Mass. App. 456') citation = case.citations.first() url = api_reverse("cases-detail", args=[citation.normalized_cite]) # should have received a redirect response = client.get(url) check_response(response, status_code=302) response = client.get(url, follow=True) check_response(response) content = response.json()['results'] case = citation.case # should only have one case returned assert len(content) == 1 assert content[0]['id'] == case.id # should only have one citation for this case citations_result = content[0]['citations'] assert len(citations_result) == 1 assert citations_result[0]['cite'] == citation.cite # allow user to enter real citation (not normalized) url = api_reverse("case-get-cite", args=[citation.cite]) response = client.get(url, follow=True) check_response(response) content = response.json()['results'] case = citation.case assert len(content) == 1 assert content[0]['id'] == case.id
def test_unauthenticated_full_case(unrestricted_case, restricted_case, client, elasticsearch): """ we should allow users to get full case without authentication if case is whitelisted we should allow users to see why they couldn't get full case if case is blacklisted """ case_url = api_reverse("cases-detail", args=[unrestricted_case.id]) response = client.get(case_url, {"full_case": "true"}) check_response(response) content = response.json() assert "casebody" in content assert type(content['casebody']['data']) is dict case_url = api_reverse("cases-detail", args=[restricted_case.id]) response = client.get(case_url, {"full_case": "true"}) check_response(response) content = response.json() casebody = content['casebody'] assert 'error_' in casebody['status'] assert not casebody['data']
def test_case_editor(reset_sequences, admin_client, auth_client, unrestricted_case_factory): unrestricted_case = unrestricted_case_factory(first_page_order=1, last_page_order=3) url = reverse('case_editor', args=[unrestricted_case.pk], host='cite') response = admin_client.get(url) check_response(response) response = auth_client.get(url) check_response(response, status_code=302) # make an edit unrestricted_case.sync_case_body_cache() body_cache = unrestricted_case.body_cache old_html = body_cache.html old_first_page = unrestricted_case.first_page description = "Made some edits" page = unrestricted_case.structure.pages.first() response = admin_client.post( url, json.dumps({ 'metadata': { 'name': [unrestricted_case.name, 'new name'], 'decision_date_original': [unrestricted_case.decision_date_original, '2020-01-01'], 'first_page': [old_first_page, 'ignore this'], 'human_corrected': [False, True], }, 'description': description, 'edit_list': { page.id: { 'BL_81.3': { 3: ["Case text 0", "Replacement text"], } } } }), content_type="application/json") check_response(response) # check OCR edit body_cache.refresh_from_db() new_html = body_cache.html assert list(unified_diff(old_html.splitlines(), new_html.splitlines(), n=0))[3:] == [ '- <h4 class="parties" id="b81-4">Case text 0</h4>', '+ <h4 class="parties" id="b81-4">Replacement text</h4>', ] # check metadata unrestricted_case.refresh_from_db() assert unrestricted_case.name == 'new name' assert unrestricted_case.decision_date_original == '2020-01-01' assert unrestricted_case.decision_date == datetime.date(year=2020, month=1, day=1) assert unrestricted_case.human_corrected is True assert unrestricted_case.first_page == old_first_page # change ignored # check log log_entry = unrestricted_case.correction_logs.first() assert log_entry.description == description assert log_entry.user_id == admin_client.auth_user.id
def test_case_series_name_redirect(client, unrestricted_case, elasticsearch): """ Test /series/volume/case/ with series redirect when not slugified""" cite = unrestricted_case.citations.first() cite_parts = re.match(r'(\S+)\s+(.*?)\s+(\S+)$', cite.cite).groups() # series is not slugified, expect redirect response = client.get( reverse('citation', args=[cite_parts[1], cite_parts[0], cite_parts[2]], host='cite')) check_response(response, status_code=302) response = client.get( reverse('citation', args=[cite_parts[1], cite_parts[0], cite_parts[2]], host='cite'), follow=True) check_response(response) # series redirect works with case_id response = client.get( reverse('citation', args=[cite_parts[1], cite_parts[0], cite_parts[2], unrestricted_case.id], host='cite')) check_response(response, status_code=302) response = client.get( reverse('citation', args=[cite_parts[1], cite_parts[0], cite_parts[2]], host='cite'), follow=True) check_response(response)
def test_registration_after_login(auth_user, auth_client): response = auth_client.get(reverse('user-details')) check_response(response) # try going to the registration page # get directed to the details page instead response = auth_client.get(reverse('register')) check_response(response, status_code=302) assert response.url == reverse('user-details') # make sure registration is still reachable after logging out auth_client.logout() response = auth_client.get(reverse('register')) check_response(response, status_code=200) assert "<title>Register | Caselaw Access Project</title>" in response.content.decode()
def test_series(client, django_assert_num_queries, volume_metadata_factory): """ Test /series/ """ # make sure we correctly handle multiple reporters with same slug volume_1, volume_2 = [volume_metadata_factory( reporter__short_name='Mass.', reporter__short_name_slug='mass', ) for _ in range(2)] response = client.get(reverse('series', args=['mass'], host='cite')) check_response(response) content = response.content.decode() for vol in (volume_1, volume_2): assert vol.volume_number in content assert vol.reporter.full_name in content # make sure we redirect if series is not slugified response = client.get(reverse('series', args=['Mass.'], host='cite')) check_response(response, status_code=302) response = client.get(reverse('series', args=['mass'], host='cite'), follow=True) check_response(response, status_code=200) # make sure we get 404 if bad series input response = client.get(reverse('series', args=['*'], host='cite')) check_response(response, status_code=404)
def test_robots(client, case): case_string = "Disallow: %s" % case.frontend_url # default version is empty: url = reverse('robots', host='cite') response = client.get(url) check_response(response, content_type="text/plain", content_includes='User-agent: *', content_excludes=case_string) # case with robots_txt_until in future is included: case.no_index = True case.robots_txt_until = timezone.now() + timedelta(days=1) case.save() check_response(client.get(url), content_type="text/plain", content_includes=case_string) # case with robots_txt_until in past is excluded: case.robots_txt_until = timezone.now() - timedelta(days=1) case.save() response = client.get(url) check_response(response, content_type="text/plain", content_includes='User-agent: *', content_excludes=case_string)
def test_flow(client, unrestricted_case, elasticsearch): """user should be able to click through to get to different tables""" # start with case response = client.get( api_reverse("cases-detail", args=[unrestricted_case.id])) check_response(response) content = response.json() # onwards to court court_url = content.get("court")["url"] assert court_url response = client.get(court_url) check_response(response) # onwards to jurisdiction jurisdiction_url = content.get("jurisdiction")["url"] assert jurisdiction_url response = client.get(jurisdiction_url) check_response(response) content = response.json() assert content.get("name") == unrestricted_case.jurisdiction.name
def test_timeline_delete(client, auth_client): tl = Timeline.objects.create(created_by=auth_client.auth_user, timeline=timeline) response = auth_client.get(retrieve_url + str(tl.id)) check_response(response, content_type="application/json") assert response.json()["timeline"]["title"] == timeline["title"] delete_url = reverse('labs:chronolawgic-api-delete', args=[str(tl.id)]) # don't allow unauthenticated users response = client.delete(delete_url) check_response(response, status_code=403, content_type="application/json") assert Timeline.objects.filter( created_by=auth_client.auth_user).count() == 1 # allow authenticated creators of timeline response = auth_client.delete(delete_url) check_response(response, content_type="application/json") assert Timeline.objects.filter( created_by=auth_client.auth_user).count() == 0
def test_harvard_access(request, restricted_case, client_fixture_name, elasticsearch): ### user with harvard access can download from harvard IPs, even without case allowance client = request.getfixturevalue(client_fixture_name) user = client.auth_user user.harvard_access = True user.case_allowance_remaining = 1 user.save() case_url = api_reverse("cases-detail", args=[restricted_case.id]) # request works when IP address provided response = client.get(case_url, {"full_case": "true"}, HTTP_CF_CONNECTING_IP='128.103.1.1') check_response(response) result = response.json() assert result['casebody']['status'] == 'ok' # no case allowance used user.refresh_from_db() assert user.case_allowance_remaining == 1 # request succeeds when IP address is wrong, using case allowance response = client.get(case_url, {"full_case": "true"}, HTTP_CF_CONNECTING_IP='1.1.1.1') check_response(response) result = response.json() assert result['casebody']['status'] == 'ok' # case allowance used user.refresh_from_db() assert user.case_allowance_remaining == 0 # request fails when case allowance exhausted response = client.get(case_url, {"full_case": "true"}, HTTP_CF_CONNECTING_IP='1.1.1.1') check_response(response) result = response.json() assert result['casebody']['status'] != 'ok'
def test_volume(client, django_assert_num_queries, case_factory, elasticsearch): """ Test /series/volume/ """ cases = [case_factory( volume__reporter__full_name='Massachusetts%s' % i, volume__reporter__short_name='Mass.', volume__reporter__short_name_slug='mass', volume__volume_number='1', volume__volume_number_slug='1', ) for i in range(3)] with django_assert_num_queries(select=1): response = client.get(reverse('volume', args=['mass', '1'], host='cite')) check_response(response) content = response.content.decode() for case in cases: assert case.reporter.full_name in content assert case.citations.first().cite in content # make sure we redirect if reporter name / series is not slugified response = client.get(reverse('volume', args=['Mass.', '1'], host='cite')) check_response(response, status_code=302) response = client.get(reverse('volume', args=['Mass.', '1'], host='cite'), follow=True) check_response(response, status_code=200)
def test_unlimited_access(auth_user, auth_client, restricted_case, elasticsearch): ### user with unlimited access should not have blacklisted cases count against them auth_user.total_case_allowance = settings.API_CASE_DAILY_ALLOWANCE auth_user.unlimited_access = True auth_user.unlimited_access_until = timedelta(hours=24) + timezone.now() auth_user.save() case_url = api_reverse("cases-detail", args=[restricted_case.id]) response = auth_client.get(case_url, {"full_case": "true"}) check_response(response) auth_user.refresh_from_db() assert auth_user.case_allowance_remaining == auth_user.total_case_allowance # total_case_allowance shouldn't matter if unlimited access is in effect auth_user.total_case_allowance = 0 auth_user.case_allowance_remaining = 0 auth_user.unlimited_access_until = None auth_user.save() response = auth_client.get(case_url, {"full_case": "true"}) check_response(response) result = response.json() casebody = result['casebody'] assert casebody['status'] == 'ok' assert type(casebody['data']) is dict # don't allow user to download blacklisted case if unlimited access has expired # and they don't have enough case allowance auth_user.total_case_allowance = 0 auth_user.case_allowance_remaining = 0 auth_user.unlimited_access_until = timezone.now() - timedelta(hours=1) auth_user.save() response = auth_client.get(case_url, {"full_case": "true"}) check_response(response) result = response.json() assert result['casebody']['status'] != 'ok'
def test_docs(client, elasticsearch, three_cases): response = client.get(reverse('docs', args=['site_features/registration'])) check_response(response)
def test_affiliated_research_access_request(auth_client, contract_approver_auth_client, mailoutbox): user = auth_client.auth_user # can view form response = auth_client.get(reverse('affiliated-research-request')) check_response(response) # can submit form values = { 'name': 'First Last', 'email': '*****@*****.**', 'institution': 'Foo Institution', 'title': 'Foo Title', 'area_of_interest': 'Foo Area of Interest' } response = auth_client.post(reverse('affiliated-research-request'), values) check_response(response, status_code=302) assert response.url == reverse('affiliated-research-request-success') contract = user.research_contracts.first() assert contract # can review contract message = mailoutbox[0].body approve_url = message.split("deny this application at ")[1].split()[0] response = contract_approver_auth_client.get(approve_url) check_response(response, content_includes=values['name']) # can deny contract response = contract_approver_auth_client.post(approve_url, { 'contract_id': contract.id, 'deny': 'true' }) check_response(response, content_includes="%s denied" % values['name']) contract.refresh_from_db() assert contract.status == 'denied' user.refresh_from_db() assert not user.unlimited_access_in_effect() message = mailoutbox[1].body assert "has been denied" in message # can approve contract contract.status = 'pending' contract.save() response = contract_approver_auth_client.post(approve_url, { 'contract_id': contract.id, 'approve': 'true' }) check_response(response, content_includes="%s approved" % values['name']) contract.refresh_from_db() assert contract.status == 'approved' assert contract.approver_signature_date assert contract.approver == contract_approver_auth_client.auth_user user.refresh_from_db() assert user.unlimited_access_in_effect() # check created contract and email message message = mailoutbox[2].body values['email'] = user.email for k, v in values.items(): assert getattr(contract, k) == v assert v in message assert v in contract.contract_html
import pytest from PIL import Image from django.conf import settings from capapi.tests.helpers import check_response from capweb.helpers import reverse, page_image_url @pytest.mark.django_db def test_nav(client, case, reporter): """ All our navigation links lead to somewhere 200 Ok """ response = client.get(reverse('home')) check_response(response) soup = BeautifulSoup(response.content.decode(), 'html.parser') dropdown_item = soup.find_all('a', {'class': 'dropdown-item'}) for a in dropdown_item: res = client.get(a.get('href')) check_response(res) nav_links = soup.find_all('a', {'class': 'nav-link'}) for a in nav_links: res = client.get(a.get('href')) try: check_response(res) except AssertionError: check_response(res, status_code=302) assert "/docs/" in res.url
def test_show_timelines(client, auth_client): response = client.get(reverse('labs:chronolawgic-dashboard')) # check to see it includes api urls since everything else is rendered in Vue check_response(response, content_includes="chronolawgic_api_create")
def test_labs_page(client): response = client.get(reverse('labs:labs')) check_response(response, content_includes="CAP LABS")
import re import pytest from capapi.tests.helpers import check_response from django.conf import settings @pytest.mark.django_db def test_get_docs_urls(client, jurisdiction, case, reporter): """ Test that every url in docs.html is functional """ settings.API_DOCS_CASE_ID = case.id response = client.get('/') html = response.content.decode() tmp_html = re.sub(";", "", html) possible_lines = tmp_html.split("'") for line in possible_lines: if line[0:4] == "http": response = client.get(line) check_response(response)
def test_timeline_update_validation(client, auth_client): tl = Timeline.objects.create(created_by=auth_client.auth_user, timeline=timeline) update_url = reverse('labs:chronolawgic-api-update', args=[str(tl.id)]) response = auth_client.post( update_url, {"timeline": { "description": "And my very best one" }}, format='json') check_response(response, status_code=400, content_type="application/json", content_includes="Timeline Missing") # missing timeline value response = auth_client.post(update_url, {"timeline": { "title": [] }}, format='json') check_response(response, status_code=400, content_type="application/json", content_includes="Wrong Data Type for title") # wrong timeline value data type response = auth_client.post(update_url, {"timeline": { "title": [] }}, format='json') check_response(response, status_code=400, content_type="application/json", content_includes="Wrong Data Type for title") # missing required case value response = auth_client.post( update_url, {"timeline": { "title": "Rad", "cases": [{ 'What even is': 'this?' }] }}, format='json') check_response(response, status_code=400, content_type="application/json", content_includes="Case Missing: name") # wrong case data type response = auth_client.post(update_url, { "timeline": { "title": "Rad", "cases": [{ 'name': ['what', 'crazy', 'data', 'you', 'have'] }] } }, format='json') check_response(response, status_code=400, content_type="application/json", content_includes="Case Has Wrong Data Type for name") # missing require event value response = auth_client.post(update_url, { "timeline": { "title": "Rad", "events": [{ 'name': 'wow', 'start_date': '1975-12-16' }] } }, format='json') check_response(response, status_code=400, content_type="application/json", content_includes="Event Missing: end_date") # wrong event data type response = auth_client.post(update_url, { "timeline": { "title": "Rad", "events": [{ 'name': 'wow', 'start_date': '1975-12-16', 'end_date': '1975-12-16', 'short_description': { 'guess': 'who' } }] } }, format='json') check_response( response, status_code=400, content_type="application/json", content_includes="Event Has Wrong Data Type for short_description") # extraneous timeline field response = auth_client.post( update_url, {"timeline": { "title": "Rad", "events": [], "helloooooo": "badata" }}, format='json') check_response(response, status_code=400, content_type="application/json", content_includes="Unexpected timeline field(s)") # extraneous event field response = auth_client.post(update_url, { "timeline": { "title": "Rad", "events": [{ 'name': 'wow', 'start_date': '1975-12-16', 'end_date': '1975-12-16', 'DOESNOTBELONG': 'here' }], } }, format='json') check_response(response, status_code=400, content_type="application/json", content_includes="Unexpected event field(s)") # extraneous case field response = auth_client.post(update_url, { "timeline": { "title": "Rad", "cases": [{ 'name': 'joe v volcano', "herring_color": 'purple' }], } }, format='json') check_response(response, status_code=400, content_type="application/json", content_includes="Unexpected case field(s)")
def test_single_case(client, auth_client, token_auth_client, case_factory, elasticsearch, response_type, django_assert_num_queries, settings): """ Test /series/volume/case/ with one matching case """ # set up for viewing html or pdf case_text = "Case HTML" unrestricted_case = case_factory(jurisdiction__whitelisted=True, body_cache__html=case_text, first_page_order=2, last_page_order=2) restricted_case = case_factory(jurisdiction__whitelisted=False, body_cache__html=case_text, first_page_order=2, last_page_order=2) if response_type == 'pdf': case_text = "REMEMBERED" unrestricted_url = unrestricted_case.get_pdf_url() url = restricted_case.get_pdf_url() content_type = 'application/pdf' else: unrestricted_url = full_url(unrestricted_case) url = full_url(restricted_case) content_type = None ### can load whitelisted case with django_assert_num_queries(select=2): check_response(client.get(unrestricted_url), content_includes=case_text, content_type=content_type) ### can load blacklisted case while logged out, via redirect # first we get redirect to JS page check_response(client.get(url, follow=True), content_includes="Click here to continue") # POSTing will set our cookies and let the case load response = client.post(reverse('set_cookie'), {'not_a_bot': 'yes', 'next': url}, follow=True) check_response(response, content_includes=case_text, content_type=content_type) session = client.session assert session['case_allowance_remaining'] == settings.API_CASE_DAILY_ALLOWANCE - 1 # we can now load directly response = client.get(url) check_response(response, content_includes=case_text, content_type=content_type) session = client.session assert session['case_allowance_remaining'] == settings.API_CASE_DAILY_ALLOWANCE - 2 # can no longer load if quota used up session['case_allowance_remaining'] = 0 session.save() response = client.get(url) if response_type == 'pdf': assert response.status_code == 302 # PDFs redirect back to HTML version if quota exhausted else: check_response(response) assert case_text not in response.content.decode() session = client.session assert session['case_allowance_remaining'] == 0 # check daily quota reset session['case_allowance_last_updated'] -= 60 * 60 * 24 + 1 session.save() response = client.get(url) check_response(response, content_includes=case_text, content_type=content_type) session = client.session assert session['case_allowance_remaining'] == settings.API_CASE_DAILY_ALLOWANCE - 1 ### can load normally as logged-in user for c in [auth_client, token_auth_client]: response = c.get(url) check_response(response, content_includes=case_text, content_type=content_type) previous_case_allowance = c.auth_user.case_allowance_remaining c.auth_user.refresh_from_db() assert c.auth_user.case_allowance_remaining == previous_case_allowance - 1
def test_download_area(client, auth_client, unlimited_auth_client, tmp_path, monkeypatch): overlay_path = Path(settings.BASE_DIR, 'downloads') underlay_path = tmp_path monkeypatch.setattr("capweb.views.download_files_storage", DownloadOverlayStorage(location=str(underlay_path))) # listing should include files from BASE_DIR/downloads as well as from donload_files_storage location underlay_path.joinpath('underlay.txt').write_text("contents") response = client.get(reverse('download-files', args=[''])) check_response(response, content_type="application/json") response_json = response.json() assert set(f['name'] for f in response_json['files']) == (set(p.name for p in overlay_path.glob('*')) | {'underlay.txt'}) - {'README.md', '.DS_Store'} # can fetch contents from both overlay and underlay, with or without auth for c in (client, unlimited_auth_client): for read_from, path, content_type in ((overlay_path, 'README.md', 'text/markdown'), (underlay_path, 'underlay.txt', 'text/plain')): response = c.get(reverse('download-files', args=[path])) check_response(response, content_type=content_type, content_includes=read_from.joinpath(path).read_text()) assert is_cached(response) # can list overlay folders response = c.get(reverse('download-files', args=['scdb/'])) check_response(response, content_type="application/json") # restricted folder underlay_path.joinpath('restricted').mkdir() underlay_path.joinpath('restricted/file.txt').write_text('contents') for test_client, allow_downloads, token in ( (client, False, 'none'), (auth_client, False, auth_client.auth_user.get_api_key()), (unlimited_auth_client, True, unlimited_auth_client.auth_user.get_api_key()) ): token_client = CapClient() token_client.credentials(HTTP_AUTHORIZATION='Token ' + token) for c in (test_client, token_client): # restricted directory response = c.get(reverse('download-files', args=['restricted/'])) check_response(response, content_type="application/json") cacheable = c == client # we can only cache for an anonymous user who didn't supply an auth header assert is_cached(response) is cacheable response_json = response.json() assert response_json['allow_downloads'] == allow_downloads assert set(f['name'] for f in response_json['files']) == {'file.txt'} # restricted file response = c.get(reverse('download-files', args=['restricted/file.txt'])) assert not is_cached(response) if allow_downloads: check_response(response, content_type="text/plain", content_includes="contents") else: check_response(response, content_type="application/json", status_code=403) # symlinks underlay_path.joinpath('folder_link').symlink_to('restricted') underlay_path.joinpath('file_link.txt').symlink_to('restricted/file.txt') for p1, p2 in (('folder_link/', 'restricted/'), ('folder_link/file.txt', 'restricted/file.txt'), ('file_link.txt', 'restricted/file.txt')): response = c.get(reverse('download-files', args=[p1])) check_response(response, status_code=302) assert response.url == reverse('download-files', args=[p2])
def test_home(client, django_assert_num_queries, reporter): """ Test / """ with django_assert_num_queries(select=2): response = client.get(reverse('cite_home', host='cite')) check_response(response, content_includes=reporter.full_name)
def test_swagger(client, url, content_type): response = client.get(url) check_response(response, content_type=content_type)
def test_case_not_found(client, django_assert_num_queries, elasticsearch): """ Test /series/volume/case/ not found """ with django_assert_num_queries(select=1): response = client.get(reverse('citation', args=['fake', '123', '456'], host='cite')) check_response(response, content_includes='Search for "123 Fake 456" in other databases')
def test_redoc(client): response = client.get(api_reverse("schema-redoc")) check_response(response, content_type="text/html")
def test_docs_default(client, elasticsearch, three_cases): response = client.get(reverse('docs', args=[''])) check_response(response, content_includes="Welcome to the Caselaw Access Project Documentation")
def test_site_limits(client, auth_client, restricted_case, mailoutbox, elasticsearch): ### registration limit ### # set signups per day to zero, downloads per day to one site_limits = SiteLimits.get() site_limits.daily_signup_limit = 0 site_limits.daily_download_limit = 1 site_limits.save() # register email = '*****@*****.**' response = client.post( reverse('register'), { 'email': email, 'first_name': 'First', 'last_name': 'Last', 'password1': 'Password2', 'password2': 'Password2', 'agreed_to_tos': 'on', }) user = CapUser.objects.get(email=email) # verify email address verify_email = mail.outbox[0].body verify_url = re.findall(r'https://\S+', verify_email)[0] response = client.get(verify_url) check_response(response, content_includes="We've verified your email address.") user.refresh_from_db() assert user.email_verified assert user.auth_token # verified user still has 0 limit assert user.total_case_allowance == 0 ### case download limit ### # can fetch one case response = auth_client.get( api_reverse('cases-detail', args=[restricted_case.id]), {'full_case': 'true'}) result = response.json() assert result['casebody']['status'] == 'ok' # cannot fetch second case response = auth_client.get( api_reverse('cases-detail', args=[restricted_case.id]), {'full_case': 'true'}) result = response.json() assert result['casebody']['status'] == 'error_sitewide_limit_exceeded' ### tracking ### # site_limits updated site_limits.refresh_from_db() assert site_limits.daily_signups == 1 assert site_limits.daily_downloads == 1 ### reporting ### daily_site_limit_reset_and_report.apply() site_limits.refresh_from_db() assert site_limits.daily_signups == 0 assert site_limits.daily_downloads == 0 last_mail = mailoutbox[-1] assert last_mail.subject == 'CAP daily usage: 1 registered users, 1 blacklisted downloads'
def test_legacy_redirect(client): response = client.get(reverse('api')) check_response(response, 302) assert "/docs/" in response.url