From 9f32285b6d1183e641a61099835f50962368825c Mon Sep 17 00:00:00 2001 From: Bryce Willey Date: Tue, 8 Jul 2025 23:24:35 -0400 Subject: [PATCH 1/8] Randomize the fake email we use to make accounts So there's never a conflict if a previous test fails. --- docassemble/EFSPIntegration/test/integration_test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docassemble/EFSPIntegration/test/integration_test.py b/docassemble/EFSPIntegration/test/integration_test.py index f0a22a6..fc3681d 100644 --- a/docassemble/EFSPIntegration/test/integration_test.py +++ b/docassemble/EFSPIntegration/test/integration_test.py @@ -3,6 +3,7 @@ import os import json import sys +import random import subprocess from docassemble.EFSPIntegration.py_efsp_client import EfspConnection, ApiResponse from pathlib import Path @@ -32,7 +33,7 @@ def get_proxy_server_ip(): def mock_person(): per = {} - per["email"] = "fakeemail-no-conflicts@example.com" + per["email"] = f"fakeemail-no-conflicts-{random.randint(0, 1_000_000)}@example.com" # Neat trick: https://stackoverflow.com/a/24448351/11416267 per["name"] = { "first": "B", From 8027190026a7eda9470ee4f49283f92a7b203788 Mon Sep 17 00:00:00 2001 From: Bryce Willey Date: Tue, 8 Jul 2025 23:29:35 -0400 Subject: [PATCH 2/8] Factored out jurisdiction variable Set just in the proxy connection object, not used anywhere else. --- .../EFSPIntegration/test/integration_test.py | 62 ++++++++----------- 1 file changed, 27 insertions(+), 35 deletions(-) diff --git a/docassemble/EFSPIntegration/test/integration_test.py b/docassemble/EFSPIntegration/test/integration_test.py index fc3681d..648273b 100644 --- a/docassemble/EFSPIntegration/test/integration_test.py +++ b/docassemble/EFSPIntegration/test/integration_test.py @@ -106,7 +106,7 @@ def test_hateos(self): or "firmattorneyservice" in url or "payments" in url ) - # and "illinois" not in url + # and jurisdiction not in url ) ): continue @@ -448,39 +448,26 @@ def test_filings(self): policy = self.basic_assert(self.proxy_conn.get_policy(court)) cdir = Path(__file__).resolve().parent - with open(cdir.joinpath("opening_affidavit_adams.json"), "r") as f: - all_vars_str = f.read() + with open(cdir.joinpath(filename), "r") as f: + all_vars = json.load(f) base_url = self.proxy_conn.base_url - fees_send = lambda: self.proxy_conn.proxy_client.post( - base_url - + f"jurisdictions/illinois/filingreview/courts/{court}/filing/fees", - data=all_vars_str, - ) - fees_resp = self.basic_assert(self.proxy_conn._call_proxy(fees_send)) - check_send = lambda: self.proxy_conn.proxy_client.get( - base_url - + f"jurisdictions/illinois/filingreview/courts/{court}/filing/check", - data=all_vars_str, - ) - checked_resp = self.basic_assert(self.proxy_conn._call_proxy(check_send)) + fees_resp = self.basic_assert(self.proxy_conn.calculate_filing_fees(court, all_vars=all_vars)) + checked_resp = self.basic_assert(self.proxy_conn.check_filing(court, all_vars=all_vars)) return - # IDK if I want to make a new filing each time, even if we cancel it - file_send = lambda: self.proxy_conn.proxy_client.post( - base_url + f"jurisdictions/illinois/filingreview/courts/{court}/filings", - data=all_vars_str, - ) - filing_resp = self.basic_assert(self.proxy_conn._call_proxy(file_send)) - for filing_id in filing_resp.data: - status_resp = self.basic_assert( - self.proxy_conn.get_filing_status(court, filing_id) - ) - detail_resp = self.basic_assert( - self.proxy_conn.get_filing(court, filing_id) - ) - cancel_resp = self.basic_assert( - self.proxy_conn.cancel_filing_status(court, filing_id) - ) + # IDK if I want to make a new filing each time, even if we cancel it + #filing_resp = self.basic_assert(self.proxy_conn.file_for_review(court, all_vars=all_vars)) + + #for filing_id in filing_resp.data["filingIds"]: + # status_resp = self.basic_assert( + # self.proxy_conn.get_filing_status(court, filing_id) + # ) + # detail_resp = self.basic_assert( + # self.proxy_conn.get_filing(court, filing_id) + # ) + # cancel_resp = self.basic_assert( + # self.proxy_conn.cancel_filing_status(court, filing_id) + # ) def test_codes(self): print("\n\n### Codes ###\n\n") @@ -504,7 +491,12 @@ def test_logs(self): assert l.split("|")[1].strip() == server_id -def main(*, base_url, api_key, user_email=None, user_password=None): +def main(*, base_url, api_key, user_email=None, user_password=None, verbose=False): + jurisdiction = 'illinois' # 'massachusetts' + court = "adams" # "appeals:acsj" + record_court = "tazewell" # "535" + docket_number = "2022-SC-000005" # "99H85SC000016" + bar_number = "6224951" # "012345A" if not base_url: base_url = get_proxy_server_ip() if not api_key: @@ -515,7 +507,7 @@ def main(*, base_url, api_key, user_email=None, user_password=None): if not user_password: user_password = os.getenv("bryce_user_password") bad_proxy = EfspConnection( - url=base_url, api_key="IntenionallyWrongKey", default_jurisdiction="illinois" + url=base_url, api_key="IntenionallyWrongKey", default_jurisdiction=jurisdiction ) intentional_bad_resp = bad_proxy.authenticate_user() if intentional_bad_resp.response_code != 403: @@ -523,11 +515,11 @@ def main(*, base_url, api_key, user_email=None, user_password=None): assert intentional_bad_resp.response_code == 403 bad_proxy.proxy_client.close() proxy_conn = EfspConnection( - url=base_url, api_key=api_key, default_jurisdiction="illinois" + url=base_url, api_key=api_key, default_jurisdiction=jurisdiction ) proxy_conn.set_verbose_logging(False) tc = TestClass( - proxy_conn, verbose=False, user_email=user_email, user_password=user_password + proxy_conn, verbose=verbose, user_email=user_email, user_password=user_password ) tc.test_authenticate() tc.test_hateos() From 8f83d227ee5cd7beb6b1c9af8db0c1269c9c44dc Mon Sep 17 00:00:00 2001 From: Bryce Willey Date: Wed, 9 Jul 2025 00:09:03 -0400 Subject: [PATCH 3/8] Make verbosity a param --- docassemble/EFSPIntegration/test/integration_test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docassemble/EFSPIntegration/test/integration_test.py b/docassemble/EFSPIntegration/test/integration_test.py index 648273b..31b9687 100644 --- a/docassemble/EFSPIntegration/test/integration_test.py +++ b/docassemble/EFSPIntegration/test/integration_test.py @@ -517,7 +517,7 @@ def main(*, base_url, api_key, user_email=None, user_password=None, verbose=Fals proxy_conn = EfspConnection( url=base_url, api_key=api_key, default_jurisdiction=jurisdiction ) - proxy_conn.set_verbose_logging(False) + proxy_conn.set_verbose_logging(verbose) tc = TestClass( proxy_conn, verbose=verbose, user_email=user_email, user_password=user_password ) @@ -545,4 +545,5 @@ def main(*, base_url, api_key, user_email=None, user_password=None, verbose=Fals main( base_url=sys.argv[1] if len(sys.argv) > 1 else None, api_key=os.getenv("PROXY_API_KEY"), + verbose=True ) From 239ab7c346b1bf7fbcd74f0437d604ec2b330780 Mon Sep 17 00:00:00 2001 From: Bryce Willey Date: Wed, 9 Jul 2025 00:10:22 -0400 Subject: [PATCH 4/8] Make court, bar_number, & docket_number variables Instead of hardcoding them in the functions themselves --- .../EFSPIntegration/test/integration_test.py | 64 +++++++++---------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/docassemble/EFSPIntegration/test/integration_test.py b/docassemble/EFSPIntegration/test/integration_test.py index 31b9687..1bd1a80 100644 --- a/docassemble/EFSPIntegration/test/integration_test.py +++ b/docassemble/EFSPIntegration/test/integration_test.py @@ -303,9 +303,9 @@ def test_users(self): self.basic_assert(self.proxy_conn.remove_user(new_id)) - def test_get_courts(self): + def test_get_courts(self, expected_court): courts = self.basic_assert(self.proxy_conn.get_courts()) - assert "jefferson" in courts.data + assert expected_court in courts.data def test_global_payment_accounts(self): print("\n\n### Global payment accounts ###\n\n") @@ -347,11 +347,11 @@ def test_global_payment_accounts(self): self.proxy_conn.remove_global_payment_account(global_account.data) ) - def test_payment_accounts(self): + def test_payment_accounts(self, court): print("\n\n### Payment accounts ###\n\n") self.basic_assert(self.proxy_conn.get_payment_account_type_list()) self.basic_assert(self.proxy_conn.get_payment_account_list()) - self.basic_assert(self.proxy_conn.get_payment_account_list("adams")) + self.basic_assert(self.proxy_conn.get_payment_account_list(court)) new_account = self.basic_assert( self.proxy_conn.create_waiver_account("New Integration Test account", False) @@ -374,7 +374,7 @@ def test_payment_accounts(self): ) self.basic_assert(self.proxy_conn.remove_payment_account(new_account.data)) - def test_court_record(self): + def test_court_record(self, court, docket_number): print("\n\n### Court record ###\n\n") # NOTE(brycew): Illinois turned off search by case name, so turning it off here. # Maybe consider testing this on another jurisdiction. @@ -382,45 +382,42 @@ def test_court_record(self): # contact["first"] = "John" # contact["last"] = "Brown" - COURT = "tazewell" - - docket_number = "2022-SC-000005" cases = self.basic_assert( self.proxy_conn.get_cases_raw( - "tazewell", docket_number=docket_number + court, docket_number=docket_number ) # person_name=contact) ) assert len(cases.data) > 0 case_id = cases.data[0]["value"]["caseTrackingID"]["value"] - case_info = self.basic_assert(self.proxy_conn.get_case(COURT, case_id)) - doc_resp = self.proxy_conn.get_document(COURT, case_id) + case_info = self.basic_assert(self.proxy_conn.get_case(court, case_id)) + doc_resp = self.proxy_conn.get_document(court, case_id) assert doc_resp.response_code == 405 serv_info = self.basic_assert( - self.proxy_conn.get_service_information(COURT, case_id) + self.proxy_conn.get_service_information(court, case_id) ) history_serv_info = self.basic_assert( - self.proxy_conn.get_service_information_history(COURT, case_id) + self.proxy_conn.get_service_information_history(court, case_id) ) if len(serv_info.data) > 0: serv_id = serv_info.data[0] - attach_cases = self.proxy_conn.get_service_attach_case_list(COURT, serv_id) + attach_cases = self.proxy_conn.get_service_attach_case_list(court, serv_id) if self.verbose: print(attach_cases) - def test_attorneys(self): + def test_attorneys(self, bar_number): print("\n\n### Attorneys ###\n\n") - new_attorney = self.proxy_conn.create_attorney( - bar_number="6224951", + new_attorney = self.basic_assert(self.proxy_conn.create_attorney( + bar_number=bar_number, first_name="Valarie", middle_name="DONTUSE_IS_REAL_PERSON", last_name="Franklin", - ) + )) assert new_attorney.response_code == 200 new_attorney_id = new_attorney.data attorney_list = self.basic_assert(self.proxy_conn.get_attorney_list()) - assert any(map(lambda a: a["barNumber"] == "6224951", attorney_list.data)) + assert any(map(lambda a: a["barNumber"] == bar_number, attorney_list.data)) updated_attorney = self.basic_assert( self.proxy_conn.update_attorney(new_attorney_id, middle_name="Lobert") @@ -435,9 +432,8 @@ def test_attorneys(self): deleted_maybe = self.proxy_conn.remove_attorney(new_attorney_id) assert deleted_maybe.response_code == 200 - def test_filings(self): + def test_filings(self, court, filename): print("\n\n### Filings ###\n\n") - court = "adams" filing_list = self.basic_assert( self.proxy_conn.get_filing_list( court, @@ -469,19 +465,19 @@ def test_filings(self): # self.proxy_conn.cancel_filing_status(court, filing_id) # ) - def test_codes(self): + def test_codes(self, court): print("\n\n### Codes ###\n\n") self.basic_assert(self.proxy_conn.get_court_list()) - self.basic_assert(self.proxy_conn.get_court("adams")) - self.basic_assert(self.proxy_conn.get_datafield("adams", "GlobalPassword")) - self.basic_assert(self.proxy_conn.get_disclaimers("adams")) + self.basic_assert(self.proxy_conn.get_court(court)) + self.basic_assert(self.proxy_conn.get_datafield(court, "GlobalPassword")) + self.basic_assert(self.proxy_conn.get_disclaimers(court)) categories = self.basic_assert( - self.proxy_conn.get_case_categories("adams") + self.proxy_conn.get_case_categories(court) ).data for idx, cat in enumerate(categories): if idx > 5: - continue - self.basic_assert(self.proxy_conn.get_case_types("adams", cat["code"])) + break + self.basic_assert(self.proxy_conn.get_case_types(court, cat["code"])) def test_logs(self): print("\n\n### Test Logs ###\n\n") @@ -526,15 +522,15 @@ def main(*, base_url, api_key, user_email=None, user_password=None, verbose=Fals tc.test_self_user() tc.test_firm() tc.test_service_contacts() - tc.test_get_courts() - tc.test_payment_accounts() - tc.test_attorneys() - tc.test_court_record() + tc.test_get_courts(court) + tc.test_payment_accounts(court) + tc.test_attorneys(bar_number) + tc.test_court_record(record_court, docket_number) tc.test_users() - tc.test_codes() + tc.test_codes(court) tc.test_logs() # TODO(brycew): needs a more up to date JSON from any filing interiview - tc.test_filings() + tc.test_filings(court, "opening_affidavit_adams.json") print("Done!") # TODO(brycew): Tyler issue, have to wait on them # tc.test_global_payment_accounts() From 5c980b244e8c0dda67b997b9c8e5f0f676d65d68 Mon Sep 17 00:00:00 2001 From: Bryce Willey Date: Wed, 9 Jul 2025 10:43:43 -0400 Subject: [PATCH 5/8] Switched to python`s unittest --- .../EFSPIntegration/test/integration_test.py | 261 ++++++++---------- 1 file changed, 117 insertions(+), 144 deletions(-) diff --git a/docassemble/EFSPIntegration/test/integration_test.py b/docassemble/EFSPIntegration/test/integration_test.py index 1bd1a80..cc28ecb 100644 --- a/docassemble/EFSPIntegration/test/integration_test.py +++ b/docassemble/EFSPIntegration/test/integration_test.py @@ -9,32 +9,17 @@ from pathlib import Path from datetime import datetime, timedelta +import unittest -def get_proxy_server_ip(): - # Figure out the ip addr of the service, assuming it's running through - # Docker compose - info_json = subprocess.check_output( - ["docker", "inspect", "efileproxyserver-efspjava"] - ) - if info_json: - info_dict = json.loads(info_json) - base_url = ( - "http://" - # + info_dict[0]["NetworkSettings"]["Networks"]["efileproxyserver_default"]["IPAddress"] - + "localhost" - + ":9000/" - ) - print("Using URL: " + base_url) - return base_url - else: - print("FAILED Can't find the docker image!") - return None +jurisdiction = "illinois" # 'massachusetts' + +base_url = None # From Env var +api_key = None # From Env var def mock_person(): per = {} per["email"] = f"fakeemail-no-conflicts-{random.randint(0, 1_000_000)}@example.com" - # Neat trick: https://stackoverflow.com/a/24448351/11416267 per["name"] = { "first": "B", "middle": "S", @@ -52,26 +37,58 @@ def mock_person(): return per -class TestClass: - def __init__( - self, proxy_conn, verbose: bool = True, user_email=None, user_password=None - ): - self.proxy_conn = proxy_conn - self.verbose = verbose - self.user_email = user_email - self.user_password = user_password +class BadAuth(unittest.TestCase): + + def test_misconfigured_proxy(self): + bad_proxy = EfspConnection( + url=base_url, + api_key="IntenionallyWrongKey", + default_jurisdiction=jurisdiction, + ) + intentional_bad_resp = bad_proxy.authenticate_user() + self.assertEqual(intentional_bad_resp.response_code, 403) + bad_proxy.proxy_client.close() + + +class TestClass(unittest.TestCase): + + def setUp(self): + # Constants + self.jurisdiction = jurisdiction + self.court = "adams" # "appeals:acsj" + self.record_court = "tazewell" # "535" + self.docket_number = "2022-SC-000005" # "99H85SC000016" + self.bar_number = "6224951" # "012345A" # This MA value is still not correct + self.filing_filename = "opening_affidavit_adams.json" # no MA equivalent yet + self.verbose = False + + # Actual setup + self.user_email = os.getenv("bryce_user_email") + self.user_password = os.getenv("bryce_user_password") + api_key = os.getenv("PROXY_API_KEY") + if not api_key: + print("You need to have the PROXY_API_KEY env var set; not running tests") + exit(2) + self.proxy_conn = EfspConnection( + url=base_url, api_key=api_key, default_jurisdiction=jurisdiction + ) + self.proxy_conn.set_verbose_logging(verbose) + self.setup_authenticate() + + def tearDown(self): + self.proxy_conn.proxy_client.close() def basic_assert(self, resp: ApiResponse): if self.verbose or not resp.is_ok(): print(resp) - assert resp.is_ok() + self.assertTrue(resp.is_ok()) return resp - def test_authenticate(self): + def setup_authenticate(self): print("\n\n### Authenticate ###\n\n") empty_resp = self.proxy_conn.authenticate_user() self.basic_assert(empty_resp) - assert len(empty_resp.data["tokens"]) == 0 + self.assertEqual(empty_resp.data["tokens"], []) resp = self.proxy_conn.authenticate_user( tyler_email=self.user_email, tyler_password=self.user_password ) @@ -127,12 +144,12 @@ def test_hateos(self): def test_self_user(self): print("\n\n### Self user ###\n\n") myself = self.basic_assert(self.proxy_conn.get_user()) - assert myself.data["middleName"] == "Steven" + self.assertEqual(myself.data["middleName"], "Steven") nm = self.basic_assert( self.proxy_conn.update_user(myself.data["userID"], middle_name="Stephen") ) bad_spelling = self.basic_assert(self.proxy_conn.get_user()) - assert bad_spelling.data["middleName"] == "Stephen" + self.assertEqual(bad_spelling.data["middleName"], "Stephen") self.basic_assert(self.proxy_conn.self_update_user(middle_name="Steven")) # Password stuff @@ -164,16 +181,12 @@ def test_self_user(self): ) ) new_notifs = self.basic_assert(self.proxy_conn.get_notification_preferences()) - assert all( - map( - lambda n: n["isActive"] == False, - filter(lambda n: n["code"] == "SERVICEUNDELIVERABLE", new_notifs.data), - ) - ) + for n in filter(lambda n: n["code"] == "SERVICEUNDELIVERABLE", new_notifs.data): + self.assertFalse(n["isActive"]) last_update = self.proxy_conn.update_notification_preferences( [{"code": "SERVICEUNDELIVERABLE", "isActive": True}] ) - assert last_update.response_code == 200 + self.assertEqual(last_update.response_code, 200) def test_service_contacts(self): print("\n\n### Service Contacts ###\n\n") @@ -212,7 +225,7 @@ def test_service_contacts(self): ) my_list = self.basic_assert(self.proxy_conn.get_service_contact_list()) - assert len(my_list.data) >= 1 + self.assertGreaterThan(len(my_list.data), 1) updated_contact = self.basic_assert( self.proxy_conn.get_service_contact(contact_id) ) @@ -303,40 +316,41 @@ def test_users(self): self.basic_assert(self.proxy_conn.remove_user(new_id)) - def test_get_courts(self, expected_court): + def test_get_courts(self): courts = self.basic_assert(self.proxy_conn.get_courts()) - assert expected_court in courts.data + assert self.court in courts.data + @unittest.skip("Tyler issue, have to wait on them") def test_global_payment_accounts(self): print("\n\n### Global payment accounts ###\n\n") all_accounts = self.proxy_conn.get_global_payment_account_list() if self.verbose: print(all_accounts) - assert all_accounts.response_code == 200 - assert all_accounts.data[0]["firmID"] is None + self.assertEqual(all_accounts.response_code, 200) + self.assertIsNone(all_accounts.data[0]["firmID"]) account_id = all_accounts.data[0]["paymentAccountID"] account = self.proxy_conn.get_global_payment_account( global_payment_account_id=account_id ) if self.verbose: print(account) - assert account.response_code == 200 - assert account.data["paymentAccountID"] == account_id + self.assertEqual(account.response_code, 200) + self.assertEqual(account.data["paymentAccountID"], account_id) update_account = self.proxy_conn.update_global_payment_account( account_id, account_name="New, Better Name" ) if self.verbose: print(update_account) - assert update_account.response_code == 200 + self.assertEqual(update_account.response_code, 200) better_account = self.proxy_conn.get_global_payment_account(account_id) - assert better_account.response_code == 200 - assert better_account.data["accountName"] == "New, Better Name" + self.assertEqual(better_account.response_code, 200) + self.assertEqual(better_account.data["accountName"], "New, Better Name") update_account = self.proxy_conn.update_global_payment_account( account_id, account_name=account.data["accountName"] ) - assert update_account.response_code == 200 + self.assertEqual(update_account.response_code, 200) global_account = self.basic_assert( self.proxy_conn.create_waiver_account( @@ -347,11 +361,11 @@ def test_global_payment_accounts(self): self.proxy_conn.remove_global_payment_account(global_account.data) ) - def test_payment_accounts(self, court): + def test_payment_accounts(self): print("\n\n### Payment accounts ###\n\n") self.basic_assert(self.proxy_conn.get_payment_account_type_list()) self.basic_assert(self.proxy_conn.get_payment_account_list()) - self.basic_assert(self.proxy_conn.get_payment_account_list(court)) + self.basic_assert(self.proxy_conn.get_payment_account_list(self.court)) new_account = self.basic_assert( self.proxy_conn.create_waiver_account("New Integration Test account", False) @@ -374,7 +388,7 @@ def test_payment_accounts(self, court): ) self.basic_assert(self.proxy_conn.remove_payment_account(new_account.data)) - def test_court_record(self, court, docket_number): + def test_court_record(self): print("\n\n### Court record ###\n\n") # NOTE(brycew): Illinois turned off search by case name, so turning it off here. # Maybe consider testing this on another jurisdiction. @@ -384,77 +398,86 @@ def test_court_record(self, court, docket_number): cases = self.basic_assert( self.proxy_conn.get_cases_raw( - court, docket_number=docket_number + self.record_court, docket_number=self.docket_number ) # person_name=contact) ) - assert len(cases.data) > 0 + self.assertGreater(len(cases.data), 0) case_id = cases.data[0]["value"]["caseTrackingID"]["value"] - case_info = self.basic_assert(self.proxy_conn.get_case(court, case_id)) - doc_resp = self.proxy_conn.get_document(court, case_id) - assert doc_resp.response_code == 405 + case_info = self.basic_assert( + self.proxy_conn.get_case(self.record_court, case_id) + ) + doc_resp = self.proxy_conn.get_document(self.record_court, case_id) + self.assertEqual(doc_resp.response_code, 405) serv_info = self.basic_assert( - self.proxy_conn.get_service_information(court, case_id) + self.proxy_conn.get_service_information(self.record_court, case_id) ) history_serv_info = self.basic_assert( - self.proxy_conn.get_service_information_history(court, case_id) + self.proxy_conn.get_service_information_history(self.record_court, case_id) ) if len(serv_info.data) > 0: serv_id = serv_info.data[0] - attach_cases = self.proxy_conn.get_service_attach_case_list(court, serv_id) + attach_cases = self.proxy_conn.get_service_attach_case_list( + self.record_court, serv_id + ) if self.verbose: print(attach_cases) - def test_attorneys(self, bar_number): + def test_attorneys(self): print("\n\n### Attorneys ###\n\n") - new_attorney = self.basic_assert(self.proxy_conn.create_attorney( - bar_number=bar_number, - first_name="Valarie", - middle_name="DONTUSE_IS_REAL_PERSON", - last_name="Franklin", - )) + new_attorney = self.basic_assert( + self.proxy_conn.create_attorney( + bar_number=self.bar_number, + first_name="Valarie", + middle_name="DONTUSE_IS_REAL_PERSON", + last_name="Franklin", + ) + ) assert new_attorney.response_code == 200 new_attorney_id = new_attorney.data attorney_list = self.basic_assert(self.proxy_conn.get_attorney_list()) - assert any(map(lambda a: a["barNumber"] == bar_number, attorney_list.data)) + assert any(map(lambda a: a["barNumber"] == self.bar_number, attorney_list.data)) updated_attorney = self.basic_assert( self.proxy_conn.update_attorney(new_attorney_id, middle_name="Lobert") ) - assert updated_attorney.data is not None + self.assertIsNotNone(updated_attorney.data) full_new_attorney = self.basic_assert( self.proxy_conn.get_attorney(new_attorney_id) ) - assert full_new_attorney.data["middleName"] == "Lobert" + self.assertEqual(full_new_attorney.data["middleName"], "Lobert") deleted_maybe = self.proxy_conn.remove_attorney(new_attorney_id) - assert deleted_maybe.response_code == 200 + self.assertEqual(deleted_maybe.response_code, 200) - def test_filings(self, court, filename): + def test_filings(self): print("\n\n### Filings ###\n\n") filing_list = self.basic_assert( self.proxy_conn.get_filing_list( - court, + self.court, start_date=datetime.today() - timedelta(days=3), before_date=datetime.today(), ) ) - policy = self.basic_assert(self.proxy_conn.get_policy(court)) + policy = self.basic_assert(self.proxy_conn.get_policy(self.court)) cdir = Path(__file__).resolve().parent - with open(cdir.joinpath(filename), "r") as f: + with open(cdir.joinpath(self.filing_filename), "r") as f: all_vars = json.load(f) base_url = self.proxy_conn.base_url - fees_resp = self.basic_assert(self.proxy_conn.calculate_filing_fees(court, all_vars=all_vars)) - checked_resp = self.basic_assert(self.proxy_conn.check_filing(court, all_vars=all_vars)) - return + fees_resp = self.basic_assert( + self.proxy_conn.calculate_filing_fees(self.court, all_vars=all_vars) + ) + checked_resp = self.basic_assert( + self.proxy_conn.check_filing(self.court, all_vars=all_vars) + ) # IDK if I want to make a new filing each time, even if we cancel it - #filing_resp = self.basic_assert(self.proxy_conn.file_for_review(court, all_vars=all_vars)) + # filing_resp = self.basic_assert(self.proxy_conn.file_for_review(court, all_vars=all_vars)) - #for filing_id in filing_resp.data["filingIds"]: + # for filing_id in filing_resp.data["filingIds"]: # status_resp = self.basic_assert( # self.proxy_conn.get_filing_status(court, filing_id) # ) @@ -465,81 +488,31 @@ def test_filings(self, court, filename): # self.proxy_conn.cancel_filing_status(court, filing_id) # ) - def test_codes(self, court): + def test_codes(self): print("\n\n### Codes ###\n\n") self.basic_assert(self.proxy_conn.get_court_list()) - self.basic_assert(self.proxy_conn.get_court(court)) - self.basic_assert(self.proxy_conn.get_datafield(court, "GlobalPassword")) - self.basic_assert(self.proxy_conn.get_disclaimers(court)) + self.basic_assert(self.proxy_conn.get_court(self.court)) + self.basic_assert(self.proxy_conn.get_datafield(self.court, "GlobalPassword")) + self.basic_assert(self.proxy_conn.get_disclaimers(self.court)) categories = self.basic_assert( - self.proxy_conn.get_case_categories(court) + self.proxy_conn.get_case_categories(self.court) ).data for idx, cat in enumerate(categories): if idx > 5: break - self.basic_assert(self.proxy_conn.get_case_types(court, cat["code"])) + self.basic_assert(self.proxy_conn.get_case_types(self.court, cat["code"])) def test_logs(self): print("\n\n### Test Logs ###\n\n") server_id = self.basic_assert(self.proxy_conn.get_server_id()).data all_logs = self.basic_assert(self.proxy_conn.get_logs()) for l in all_logs.data: - assert l.split("|")[1].strip() == server_id - - -def main(*, base_url, api_key, user_email=None, user_password=None, verbose=False): - jurisdiction = 'illinois' # 'massachusetts' - court = "adams" # "appeals:acsj" - record_court = "tazewell" # "535" - docket_number = "2022-SC-000005" # "99H85SC000016" - bar_number = "6224951" # "012345A" - if not base_url: - base_url = get_proxy_server_ip() - if not api_key: - print("You need to have the PROXY_API_KEY env var set; not running tests") - return 1 - if not user_email: - user_email = os.getenv("bryce_user_email") - if not user_password: - user_password = os.getenv("bryce_user_password") - bad_proxy = EfspConnection( - url=base_url, api_key="IntenionallyWrongKey", default_jurisdiction=jurisdiction - ) - intentional_bad_resp = bad_proxy.authenticate_user() - if intentional_bad_resp.response_code != 403: - print(intentional_bad_resp) - assert intentional_bad_resp.response_code == 403 - bad_proxy.proxy_client.close() - proxy_conn = EfspConnection( - url=base_url, api_key=api_key, default_jurisdiction=jurisdiction - ) - proxy_conn.set_verbose_logging(verbose) - tc = TestClass( - proxy_conn, verbose=verbose, user_email=user_email, user_password=user_password - ) - tc.test_authenticate() - tc.test_hateos() - tc.test_self_user() - tc.test_firm() - tc.test_service_contacts() - tc.test_get_courts(court) - tc.test_payment_accounts(court) - tc.test_attorneys(bar_number) - tc.test_court_record(record_court, docket_number) - tc.test_users() - tc.test_codes(court) - tc.test_logs() - # TODO(brycew): needs a more up to date JSON from any filing interiview - tc.test_filings(court, "opening_affidavit_adams.json") - print("Done!") - # TODO(brycew): Tyler issue, have to wait on them - # tc.test_global_payment_accounts() - proxy_conn.proxy_client.close() + self.assertEqual(l.split("|")[1].strip(), server_id) if __name__ == "__main__": - main( - base_url=sys.argv[1] if len(sys.argv) > 1 else None, - api_key=os.getenv("PROXY_API_KEY"), - verbose=True - ) + base_url = os.getenv("PROXY_URL") + if not base_url: + print("Need to pass the Proxy Server URL") + exit(1) + unittest.main() From d99c2d86f124a81146e731469124433f18a479c7 Mon Sep 17 00:00:00 2001 From: Bryce Willey Date: Wed, 9 Jul 2025 11:18:39 -0400 Subject: [PATCH 6/8] Change email / password env vars to not be my name Lol, I have no idea why I thought that was a good idea in the first place. --- .../EFSPIntegration/test/integration_test.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/docassemble/EFSPIntegration/test/integration_test.py b/docassemble/EFSPIntegration/test/integration_test.py index cc28ecb..af43a24 100644 --- a/docassemble/EFSPIntegration/test/integration_test.py +++ b/docassemble/EFSPIntegration/test/integration_test.py @@ -1,5 +1,14 @@ #! /usr/bin/env python3 +""" +Env vars needed to run: + +* PROXY_URL: URL where the EfileProxyServer is running +* PROXY_API_KEY: the API Key generated from the running EfileProxyServer +* TYLER_USER_EMAIL: the email of a user account in the specific jurisdiction of Tyler's EFM (should be a firm account) +* TYLER_USER_PASSWORD: the password for that user account +""" + import os import json import sys @@ -63,8 +72,8 @@ def setUp(self): self.verbose = False # Actual setup - self.user_email = os.getenv("bryce_user_email") - self.user_password = os.getenv("bryce_user_password") + self.user_email = os.getenv("TYLER_USER_EMAIL") + self.user_password = os.getenv("TYLER_USER_PASSWORD") api_key = os.getenv("PROXY_API_KEY") if not api_key: print("You need to have the PROXY_API_KEY env var set; not running tests") @@ -144,7 +153,6 @@ def test_hateos(self): def test_self_user(self): print("\n\n### Self user ###\n\n") myself = self.basic_assert(self.proxy_conn.get_user()) - self.assertEqual(myself.data["middleName"], "Steven") nm = self.basic_assert( self.proxy_conn.update_user(myself.data["userID"], middle_name="Stephen") ) From 601570cb21d7f51b627f25346a0ade7b3c3c71d4 Mon Sep 17 00:00:00 2001 From: Bryce Willey Date: Wed, 9 Jul 2025 11:26:18 -0400 Subject: [PATCH 7/8] Adjust GitHub Actions to integration test changes --- .github/workflows/integration_test.yml | 22 ---------------------- .github/workflows/unittests.yml | 16 ++++++++++++++-- 2 files changed, 14 insertions(+), 24 deletions(-) delete mode 100644 .github/workflows/integration_test.yml diff --git a/.github/workflows/integration_test.yml b/.github/workflows/integration_test.yml deleted file mode 100644 index b0a9293..0000000 --- a/.github/workflows/integration_test.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Run python-only integration tests - -on: - push: - workflow_dispatch: - -env: - PROXY_API_KEY: ${{ secrets.EFILE_PROXY_API_KEY }} - bryce_user_email: ${{ secrets.TYLER_EMAIL }} - bryce_user_password: ${{ secrets.TYLER_PASSWORD }} - -jobs: - integration-tests: - runs-on: ubuntu-latest - name: Run python only integration tests - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 - with: - python-version: '3.9' - - run: pip install . - - run: python -m docassemble.EFSPIntegration.test.integration_test https://efile-test.suffolklitlab.org diff --git a/.github/workflows/unittests.yml b/.github/workflows/unittests.yml index ab8af7b..8547da8 100644 --- a/.github/workflows/unittests.yml +++ b/.github/workflows/unittests.yml @@ -1,12 +1,24 @@ -name: Run python only unit tests and mypy +name: Run mypy and python-only unit and integration tests on: push: workflow_dispatch: +env: + PROXY_URL: https://efile-test.suffolklitlab.org + PROXY_API_KEY: ${{ secrets.EFILE_PROXY_API_KEY }} + TYLER_USER_EMAIL: ${{ secrets.TYLER_EMAIL }} + TYLER_USER_PASSWORD: ${{ secrets.TYLER_PASSWORD }} + +# Allow only one concurrent test-run, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as stopping integration tests mid-run could end up in a bad state +concurrency: + group: "tests" + cancel-in-progress: false + jobs: test-efspintegration: runs-on: ubuntu-latest - name: Run python only unit tests + name: Run python-only unit and integration tests steps: - uses: SuffolkLITLab/ALActions/pythontests@main From d6b2ea474d6e95e8a6f68550eeac828524440d9b Mon Sep 17 00:00:00 2001 From: Bryce Willey Date: Wed, 9 Jul 2025 11:51:06 -0400 Subject: [PATCH 8/8] Get proxy test to run with unittest discover --- docassemble/EFSPIntegration/conversions.py | 2 +- ...integration_test.py => test_proxy_conn.py} | 33 ++++++++++++------- setup.py | 5 ++- 3 files changed, 24 insertions(+), 16 deletions(-) rename docassemble/EFSPIntegration/test/{integration_test.py => test_proxy_conn.py} (96%) diff --git a/docassemble/EFSPIntegration/conversions.py b/docassemble/EFSPIntegration/conversions.py index bcc74fe..528f466 100644 --- a/docassemble/EFSPIntegration/conversions.py +++ b/docassemble/EFSPIntegration/conversions.py @@ -408,7 +408,7 @@ def chain_xml(xml_val, elems: List[Union[str, int]]): val = xml_val for idx, elem in enumerate(elems): if not val: - log(f"No {elem} ({idx}) in {xml_val} ({elems})") + log(f"No `{elem}` ({idx}) in `{xml_val}` ({elems})") return None if isinstance(val, dict): val = val.get(elem) or {} diff --git a/docassemble/EFSPIntegration/test/integration_test.py b/docassemble/EFSPIntegration/test/test_proxy_conn.py similarity index 96% rename from docassemble/EFSPIntegration/test/integration_test.py rename to docassemble/EFSPIntegration/test/test_proxy_conn.py index af43a24..b152b30 100644 --- a/docassemble/EFSPIntegration/test/integration_test.py +++ b/docassemble/EFSPIntegration/test/test_proxy_conn.py @@ -22,8 +22,8 @@ jurisdiction = "illinois" # 'massachusetts' -base_url = None # From Env var -api_key = None # From Env var +base_url = os.getenv("PROXY_URL") +api_key = os.getenv("PROXY_API_KEY") def mock_person(): @@ -49,6 +49,9 @@ def mock_person(): class BadAuth(unittest.TestCase): def test_misconfigured_proxy(self): + if not base_url: + print("Need to pass the Proxy Server URL") + exit(1) bad_proxy = EfspConnection( url=base_url, api_key="IntenionallyWrongKey", @@ -58,6 +61,17 @@ def test_misconfigured_proxy(self): self.assertEqual(intentional_bad_resp.response_code, 403) bad_proxy.proxy_client.close() + def test_good_but_no_password_proxy(self): + good_proxy = EfspConnection( + url=base_url, + api_key=api_key, + default_jurisdiction=jurisdiction, + ) + + empty_resp = good_proxy.authenticate_user() + self.assertTrue(empty_resp.is_ok()) + self.assertEqual(empty_resp.data["tokens"], {}) + class TestClass(unittest.TestCase): @@ -74,14 +88,16 @@ def setUp(self): # Actual setup self.user_email = os.getenv("TYLER_USER_EMAIL") self.user_password = os.getenv("TYLER_USER_PASSWORD") - api_key = os.getenv("PROXY_API_KEY") + if not base_url: + print("Need to pass the Proxy Server URL") + exit(1) if not api_key: print("You need to have the PROXY_API_KEY env var set; not running tests") exit(2) self.proxy_conn = EfspConnection( url=base_url, api_key=api_key, default_jurisdiction=jurisdiction ) - self.proxy_conn.set_verbose_logging(verbose) + self.proxy_conn.set_verbose_logging(self.verbose) self.setup_authenticate() def tearDown(self): @@ -95,9 +111,6 @@ def basic_assert(self, resp: ApiResponse): def setup_authenticate(self): print("\n\n### Authenticate ###\n\n") - empty_resp = self.proxy_conn.authenticate_user() - self.basic_assert(empty_resp) - self.assertEqual(empty_resp.data["tokens"], []) resp = self.proxy_conn.authenticate_user( tyler_email=self.user_email, tyler_password=self.user_password ) @@ -233,7 +246,7 @@ def test_service_contacts(self): ) my_list = self.basic_assert(self.proxy_conn.get_service_contact_list()) - self.assertGreaterThan(len(my_list.data), 1) + self.assertGreater(len(my_list.data), 1) updated_contact = self.basic_assert( self.proxy_conn.get_service_contact(contact_id) ) @@ -519,8 +532,4 @@ def test_logs(self): if __name__ == "__main__": - base_url = os.getenv("PROXY_URL") - if not base_url: - print("Need to pass the Proxy Server URL") - exit(1) unittest.main() diff --git a/setup.py b/setup.py index b237463..4361af0 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,5 @@ import os -from setuptools import setup, find_packages +from setuptools import setup, find_namespace_packages from fnmatch import fnmatchcase from distutils.util import convert_path @@ -50,8 +50,7 @@ def find_package_data(where='.', package='', exclude=standard_exclude, exclude_d author_email='bwilley@suffolk.edu', license='The MIT License (MIT)', url='https://github.com/SuffolkLITLab/docassemble-EFSPIntegration', - packages=find_packages(), - namespace_packages=['docassemble'], + packages=find_namespace_packages(), install_requires=['docassemble.AssemblyLine>=2.18.0', 'docassemble.ALToolbox>=0.6.2', 'requests>=2.25.1'], zip_safe=False, package_data=find_package_data(where='docassemble/EFSPIntegration/', package='docassemble.EFSPIntegration'),