diff --git a/tests/data/doctest_project.xml b/tests/data/doctest_project.xml
index 0af6a82a..2de7f3ec 100644
--- a/tests/data/doctest_project.xml
+++ b/tests/data/doctest_project.xml
@@ -38,6 +38,9 @@
<p>Thank you!</p>" offline_instructions="" acknowledgement="<p><strong>Thank you for taking the survey.</strong></p>
<p>Have a nice day!</p>" stop_action_acknowledgement="" stop_action_delete_response="0" question_by_section="0" display_page_number="0" question_auto_numbering="1" survey_enabled="1" save_and_return="0" save_and_return_code_bypass="0" logo="" hide_title="0" view_results="0" min_responses_view_results="10" check_diversity_view_results="0" end_survey_redirect_url="" survey_expiration="" promis_skip_question="0" survey_auth_enabled_single="0" edit_completed_response="0" hide_back_button="0" show_required_field_text="1" confirmation_email_subject="" confirmation_email_content="" confirmation_email_from="" confirmation_email_from_display="" confirmation_email_attach_pdf="0" confirmation_email_attachment="" text_to_speech="0" text_to_speech_language="en" end_survey_redirect_next_survey="0" end_survey_redirect_next_survey_logic="" theme="" text_size="1" font_family="16" theme_text_buttons="" theme_bg_page="" theme_text_title="" theme_bg_title="" theme_text_sectionheader="" theme_bg_sectionheader="" theme_text_question="" theme_bg_question="" enhanced_choices="0" repeat_survey_enabled="0" repeat_survey_btn_text="" repeat_survey_btn_location="HIDDEN" response_limit="" response_limit_include_partials="1" response_limit_custom_text="<p>Thank you for your interest; however, the survey is closed because the maximum number of responses has been reached.</p>" survey_time_limit_days="" survey_time_limit_hours="" survey_time_limit_minutes="" email_participant_field="" end_of_survey_pdf_download="0" pdf_save_to_field="" pdf_save_to_event_id="" pdf_auto_archive="0" pdf_econsent_version="" pdf_econsent_type="" pdf_econsent_firstname_field="" pdf_econsent_firstname_event_id="" pdf_econsent_lastname_field="" pdf_econsent_lastname_event_id="" pdf_econsent_dob_field="" pdf_econsent_dob_event_id="" pdf_econsent_allow_edit="1" pdf_econsent_signature_field1="" pdf_econsent_signature_field2="" pdf_econsent_signature_field3="" pdf_econsent_signature_field4="" pdf_econsent_signature_field5=""/>
+
+
+
diff --git a/tests/data/test_simple_project.xml b/tests/data/test_simple_project.xml
index d05142a6..1cb8f527 100644
--- a/tests/data/test_simple_project.xml
+++ b/tests/data/test_simple_project.xml
@@ -30,6 +30,9 @@
+
+
+
diff --git a/tests/integration/test_simple_project.py b/tests/integration/test_simple_project.py
index d4ec0680..a29ce67f 100644
--- a/tests/integration/test_simple_project.py
+++ b/tests/integration/test_simple_project.py
@@ -112,6 +112,37 @@ def test_export_users(simple_project):
assert users[0]["api_export"] == 1
+@pytest.mark.integration
+def test_export_user_roles(simple_project):
+ user_roles = simple_project.export_user_roles()
+ assert len(user_roles) == 1
+ assert user_roles[0]["role_label"] == "Example Role"
+
+
+@pytest.mark.integration
+def test_export_import_user_role_assignments(simple_project):
+ new_user = "pandeharris@gmail.com"
+ simple_project.import_users([{"username": new_user}])
+
+ example_role_name = simple_project.export_user_roles()[0]["unique_role_name"]
+
+ res = simple_project.import_user_role_assignment(
+ [{"username": new_user, "unique_role_name": example_role_name}]
+ )
+ assert res == 1
+
+ user_role_assignments = simple_project.export_user_role_assignment()
+ test_user_role_name = [
+ user_role["unique_role_name"]
+ for user_role in user_role_assignments
+ if user_role["username"] == new_user
+ ][0]
+ assert test_user_role_name == example_role_name
+ # cleanup
+ res = simple_project.delete_users([new_user])
+ assert res == 1
+
+
@pytest.mark.integration
def test_export_dags(simple_project):
dags = simple_project.export_dags(format_type="df")
diff --git a/tests/unit/callback_utils.py b/tests/unit/callback_utils.py
index f6691a54..2d385077 100644
--- a/tests/unit/callback_utils.py
+++ b/tests/unit/callback_utils.py
@@ -519,6 +519,45 @@ def handle_user_request(**kwargs) -> MockResponse:
return (201, headers, resp)
+def handle_user_role_request(**kwargs) -> MockResponse:
+ """Handle user role requests"""
+ headers = kwargs["headers"]
+ data = kwargs["data"]
+ # user import (JSON only)
+ if "data" in str(data):
+ resp = 1
+ # user export (JSON only)
+ else:
+ resp = [
+ {
+ "unique_role_name": "Role Name",
+ "role_label": "Test role",
+ "design": "0",
+ "user_rights": "0",
+ "data_access_groups": "0",
+ "data_export": "0",
+ "reports": "0",
+ "stats_and_charts": "0",
+ }
+ ]
+
+ return (201, headers, json.dumps(resp))
+
+
+def handle_user_role_assignment_request(**kwargs) -> MockResponse:
+ """Handle user role mapping requests"""
+ headers = kwargs["headers"]
+ data = kwargs["data"]
+ # user import (JSON only)
+ if "data" in str(data):
+ resp = 1
+ # user export (JSON only)
+ else:
+ resp = [{"username": "test user", "unique_role_name": "Role Name"}]
+
+ return (201, headers, json.dumps(resp))
+
+
# pylint: disable=unused-argument
def handle_simple_project_version_request(**kwargs) -> MockResponse:
"""Handle REDCap version request"""
@@ -587,6 +626,8 @@ def get_simple_project_request_handler(request_type: str) -> Callable:
"report": handle_simple_project_reports_request,
"user": handle_user_request,
"userDagMapping": handle_user_dag_assignment_request,
+ "userRole": handle_user_role_request,
+ "userRoleMapping": handle_user_role_assignment_request,
"version": handle_simple_project_version_request,
}
diff --git a/tests/unit/test_simple_project.py b/tests/unit/test_simple_project.py
index 3ee3ac12..f6c6034f 100644
--- a/tests/unit/test_simple_project.py
+++ b/tests/unit/test_simple_project.py
@@ -215,6 +215,30 @@ def test_user_delete(simple_project):
assert res == "1"
+def test_user_role_export(simple_project):
+ res = simple_project.export_user_roles()
+ assert len(res) == 1
+
+
+def test_user_role_import(simple_project):
+ new_role = [{"role_label": "New role"}]
+
+ res = simple_project.import_user_roles(new_role)
+ assert res == 1
+
+
+def test_export_user_role_assignment(simple_project):
+ res = simple_project.export_user_role_assignment()
+ assert len(res) == 1
+
+
+def test_import_user_role_assignment(simple_project):
+ new_role_assignment = [{"unique_role_name": "test role", "username": "test user"}]
+
+ res = simple_project.import_user_role_assignment(new_role_assignment)
+ assert res == 1
+
+
def test_generate_next_record_name(simple_project):
next_name = simple_project.generate_next_record_name()