From a8c0902e361b289e628c8508c42303acbb0de368 Mon Sep 17 00:00:00 2001
From: Carlos Vega <carlos.vega@lih.lu>
Date: Thu, 29 Aug 2024 14:02:46 +0200
Subject: [PATCH] moved redcap test instance token and url to settings

---
 smash/smash/settings.py      |   5 +
 smash/web/tests/functions.py | 308 ++++++++++++++++++++---------------
 2 files changed, 185 insertions(+), 128 deletions(-)

diff --git a/smash/smash/settings.py b/smash/smash/settings.py
index 53366991..5d3a28ae 100644
--- a/smash/smash/settings.py
+++ b/smash/smash/settings.py
@@ -23,6 +23,11 @@ PROJECT_PATH = os.path.abspath(os.path.dirname(__file__))
 # Quick-start development settings - unsuitable for production
 # See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/
 
+# To run the unit tests we need a redcap instance.
+# UL
+REDCAP_TEST_API_TOKEN = "5DC21D45E3A2E068659F11046EA88734"
+REDCAP_TEST_URL = "https://luxparktest.lcsb.uni.lu/redcap/"
+
 COPYRIGHT_NOTE = "2024 Bioinformatics Core, Luxembourg Centre for Systems Biomedicine"
 
 DEBUG = True
diff --git a/smash/web/tests/functions.py b/smash/web/tests/functions.py
index 51d91ea3..60eddf74 100644
--- a/smash/web/tests/functions.py
+++ b/smash/web/tests/functions.py
@@ -6,14 +6,46 @@ from typing import Union
 from django.contrib.auth.models import Permission
 from django.contrib.auth import get_user_model
 from django.utils.timezone import make_aware, is_aware
-
-from web.models import Location, AppointmentType, StudySubject, Worker, Visit, Appointment, ConfigurationItem, \
-    Language, ContactAttempt, FlyingTeam, Availability, Subject, Study, StudyColumns, StudyNotificationParameters, \
-    VoucherType, VoucherTypePrice, Voucher, Room, Item, WorkerStudyRole, StudyRedCapColumns, EtlColumnMapping, \
-    SubjectImportData, SubjectType
-from web.models.constants import REDCAP_TOKEN_CONFIGURATION_TYPE, REDCAP_BASE_URL_CONFIGURATION_TYPE, \
-    SEX_CHOICES_MALE, CONTACT_TYPES_PHONE, \
-    MONDAY_AS_DAY_OF_WEEK, COUNTRY_AFGHANISTAN_ID, VOUCHER_STATUS_NEW, GLOBAL_STUDY_ID, DEFAULT_LOCALE_NAME
+from django.conf import settings
+
+from web.models import (
+    Location,
+    AppointmentType,
+    StudySubject,
+    Worker,
+    Visit,
+    Appointment,
+    ConfigurationItem,
+    Language,
+    ContactAttempt,
+    FlyingTeam,
+    Availability,
+    Subject,
+    Study,
+    StudyColumns,
+    StudyNotificationParameters,
+    VoucherType,
+    VoucherTypePrice,
+    Voucher,
+    Room,
+    Item,
+    WorkerStudyRole,
+    StudyRedCapColumns,
+    EtlColumnMapping,
+    SubjectImportData,
+    SubjectType,
+)
+from web.models.constants import (
+    REDCAP_TOKEN_CONFIGURATION_TYPE,
+    REDCAP_BASE_URL_CONFIGURATION_TYPE,
+    SEX_CHOICES_MALE,
+    CONTACT_TYPES_PHONE,
+    MONDAY_AS_DAY_OF_WEEK,
+    COUNTRY_AFGHANISTAN_ID,
+    VOUCHER_STATUS_NEW,
+    GLOBAL_STUDY_ID,
+    DEFAULT_LOCALE_NAME,
+)
 from web.models.worker_study_role import ROLE_CHOICES_DOCTOR, WORKER_VOUCHER_PARTNER
 from web.redcap_connector import RedcapSubject
 from web.views.notifications import get_today_midnight_date
@@ -37,10 +69,12 @@ def create_voucher_type():
 
 
 def create_voucher_type_price():
-    return VoucherTypePrice.objects.create(voucher_type=create_voucher_type(),
-                                           price=12.34,
-                                           start_date=get_today_midnight_date(),
-                                           end_date=get_today_midnight_date())
+    return VoucherTypePrice.objects.create(
+        voucher_type=create_voucher_type(),
+        price=12.34,
+        start_date=get_today_midnight_date(),
+        end_date=get_today_midnight_date(),
+    )
 
 
 def create_empty_study_columns():
@@ -68,8 +102,9 @@ def create_study(name="test"):
     study_columns = StudyColumns.objects.create()
     notification_parameters = StudyNotificationParameters.objects.create()
     redcap_columns = StudyRedCapColumns.objects.create()
-    return Study.objects.create(name=name, columns=study_columns, notification_parameters=notification_parameters,
-                                redcap_columns=redcap_columns)
+    return Study.objects.create(
+        name=name, columns=study_columns, notification_parameters=notification_parameters, redcap_columns=redcap_columns
+    )
 
 
 TEST_ID_COUNTER = 0
@@ -90,14 +125,16 @@ def create_voucher(study_subject=None, partner=None, worker=None):
     if worker is None:
         worker = create_worker()
     number = str(get_test_id())
-    return Voucher.objects.create(number=number,
-                                  study_subject=study_subject,
-                                  issue_date=get_today_midnight_date(),
-                                  expiry_date=get_today_midnight_date(),
-                                  voucher_type=create_voucher_type(),
-                                  usage_partner=partner,
-                                  issue_worker=worker,
-                                  status=VOUCHER_STATUS_NEW)
+    return Voucher.objects.create(
+        number=number,
+        study_subject=study_subject,
+        issue_date=get_today_midnight_date(),
+        expiry_date=get_today_midnight_date(),
+        voucher_type=create_voucher_type(),
+        usage_partner=partner,
+        issue_worker=worker,
+        status=VOUCHER_STATUS_NEW,
+    )
 
 
 def create_empty_notification_parameters():
@@ -158,7 +195,7 @@ def get_test_study() -> Study:
         return create_study("test-study")
 
 
-def create_appointment_type(code='C', default_duration=10, description='test'):
+def create_appointment_type(code="C", default_duration=10, description="test"):
     return AppointmentType.objects.create(
         code=code,
         default_duration=default_duration,
@@ -172,26 +209,25 @@ def create_contact_attempt(subject=None, worker=None):
     if worker is None:
         worker = create_worker()
 
-    return ContactAttempt.objects.create(subject=subject,
-                                         worker=worker,
-                                         type=CONTACT_TYPES_PHONE,
-                                         datetime_when=get_today_midnight_date(),
-                                         success=True,
-                                         comment="Successful contact attempt",
-                                         )
+    return ContactAttempt.objects.create(
+        subject=subject,
+        worker=worker,
+        type=CONTACT_TYPES_PHONE,
+        datetime_when=get_today_midnight_date(),
+        success=True,
+        comment="Successful contact attempt",
+    )
 
 
 def create_subject():
     return Subject.objects.create(
-        first_name="Piotr",
-        last_name="Gawron",
-        sex=SEX_CHOICES_MALE,
-        country_id=COUNTRY_AFGHANISTAN_ID
+        first_name="Piotr", last_name="Gawron", sex=SEX_CHOICES_MALE, country_id=COUNTRY_AFGHANISTAN_ID
     )
 
 
-def create_study_subject(subject_id: int = 1, subject: Subject = None, nd_number: str = 'ND0001',
-                         study: Study = None) -> StudySubject:
+def create_study_subject(
+    subject_id: int = 1, subject: Subject = None, nd_number: str = "ND0001", study: Study = None
+) -> StudySubject:
     if study is None:
         study = get_test_study()
     if subject is None:
@@ -201,7 +237,7 @@ def create_study_subject(subject_id: int = 1, subject: Subject = None, nd_number
         type=get_control_subject_type(),
         screening_number="piotr's number" + str(subject_id),
         study=study,
-        subject=subject
+        subject=subject,
     )
     if nd_number is not None:  # null value in column "nd_number" violates not-null constraint
         study_subject.nd_number = nd_number
@@ -211,11 +247,11 @@ def create_study_subject(subject_id: int = 1, subject: Subject = None, nd_number
 
 
 def get_control_subject_type() -> SubjectType:
-    return SubjectType.objects.filter(name='CONTROL').first()
+    return SubjectType.objects.filter(name="CONTROL").first()
 
 
 def get_patient_subject_type() -> SubjectType:
-    return SubjectType.objects.filter(name='PATIENT').first()
+    return SubjectType.objects.filter(name="PATIENT").first()
 
 
 def create_study_subject_with_multiple_screening_numbers(subject_id=1, subject=None, screening_number=None):
@@ -223,13 +259,13 @@ def create_study_subject_with_multiple_screening_numbers(subject_id=1, subject=N
         subject = create_subject()
 
     if screening_number is None:
-        screening_number = f'E-00{subject_id}; L-00{subject_id}'
+        screening_number = f"E-00{subject_id}; L-00{subject_id}"
     return StudySubject.objects.create(
         default_location=get_test_location(),
         type=get_control_subject_type(),
         screening_number=screening_number,
         study=get_test_study(),
-        subject=subject
+        subject=subject,
     )
 
 
@@ -239,15 +275,12 @@ def create_red_cap_subject():
     return result
 
 
-def create_user(username: str = None, password: str = None, email: str = 'jacob@bla') -> get_user_model():
+def create_user(username: str = None, password: str = None, email: str = "jacob@bla") -> get_user_model():
     if username is None:
-        username = 'piotr'
+        username = "piotr"
     if password is None:
-        password = 'top_secret'
-    user = get_user_model().objects.create_user(
-        username=username,
-        email=email,
-        password=password)
+        password = "top_secret"
+    user = get_user_model().objects.create_user(username=username, email=email, password=password)
 
     create_worker(user)
     return user
@@ -262,49 +295,48 @@ def add_permissions_to_worker(worker, codenames):
 
 def create_worker(user=None, with_test_location=False):
     worker = Worker.objects.create(
-        first_name='piotr',
+        first_name="piotr",
         last_name="gawron",
-        email='jacob@bla.com',
+        email="jacob@bla.com",
         user=user,
         specialization="spec",
         unit="LCSB",
-        phone_number="0123456789"
+        phone_number="0123456789",
     )
     if with_test_location:
         worker.locations.set([get_test_location()])
         worker.save()
-    WorkerStudyRole.objects.create(
-        worker=worker, study_id=GLOBAL_STUDY_ID, name=ROLE_CHOICES_DOCTOR)
+    WorkerStudyRole.objects.create(worker=worker, study_id=GLOBAL_STUDY_ID, name=ROLE_CHOICES_DOCTOR)
     return worker
 
 
 def create_voucher_partner():
     worker = Worker.objects.create(
-        first_name='piotr',
+        first_name="piotr",
         last_name="gawron",
-        email='jacob@bla.com',
+        email="jacob@bla.com",
         specialization="spec",
         unit="LCSB",
-        phone_number="0123456789"
+        phone_number="0123456789",
     )
-    WorkerStudyRole.objects.create(
-        worker=worker, study_id=GLOBAL_STUDY_ID, name=WORKER_VOUCHER_PARTNER)
+    WorkerStudyRole.objects.create(worker=worker, study_id=GLOBAL_STUDY_ID, name=WORKER_VOUCHER_PARTNER)
     return worker
 
 
 def create_availability(worker=None, available_from=None, available_till=None, day_number=MONDAY_AS_DAY_OF_WEEK):
     if available_from is None:
-        available_from = '8:00'
+        available_from = "8:00"
     if available_till is None:
-        available_till = '18:00'
+        available_till = "18:00"
 
     if worker is None:
         worker = create_worker()
-    availability = Availability.objects.create(person=worker,
-                                               day_number=day_number,
-                                               available_from=available_from,
-                                               available_till=available_till,
-                                               )
+    availability = Availability.objects.create(
+        person=worker,
+        day_number=day_number,
+        available_from=available_from,
+        available_till=available_till,
+    )
     return availability
 
 
@@ -315,10 +347,9 @@ def create_visit(subject: StudySubject = None, datetime_begin=None, datetime_end
         datetime_begin = get_today_midnight_date() + datetime.timedelta(days=-31)
     if datetime_end is None:
         datetime_end = get_today_midnight_date() + datetime.timedelta(days=31)
-    return Visit.objects.create(datetime_begin=datetime_begin,
-                                datetime_end=datetime_end,
-                                subject=subject,
-                                is_finished=False)
+    return Visit.objects.create(
+        datetime_begin=datetime_begin, datetime_end=datetime_end, subject=subject, is_finished=False
+    )
 
 
 def create_appointment(visit=None, when=None, length=30) -> Appointment:
@@ -339,15 +370,14 @@ def create_appointment(visit=None, when=None, length=30) -> Appointment:
         length=length,
         location=get_test_location(),
         status=Appointment.APPOINTMENT_STATUS_SCHEDULED,
-        datetime_when=when_datetime)
+        datetime_when=when_datetime,
+    )
 
 
 def create_appointment_without_visit(when=None, length=30):
     return Appointment.objects.create(
-        length=length,
-        location=get_test_location(),
-        status=Appointment.APPOINTMENT_STATUS_SCHEDULED,
-        datetime_when=when)
+        length=length, location=get_test_location(), status=Appointment.APPOINTMENT_STATUS_SCHEDULED, datetime_when=when
+    )
 
 
 def create_configuration_item():
@@ -366,19 +396,24 @@ def create_flying_team(place=None):
     return result
 
 
-def create_item(name='Test item', is_fixed=False, disposable=False):
+def create_item(name="Test item", is_fixed=False, disposable=False):
     item = Item(name=name, is_fixed=is_fixed, disposable=disposable)
     item.save()
     return item
 
 
-def create_room(owner='Test owner', city='Test city',
-                address='Test address', equipment=None,
-                floor=1, is_vehicle=False, room_number=1):
+def create_room(
+    owner="Test owner",
+    city="Test city",
+    address="Test address",
+    equipment=None,
+    floor=1,
+    is_vehicle=False,
+    room_number=1,
+):
     if equipment is None:
         equipment = []
-    room = Room(owner=owner, city=city, address=address,
-                floor=floor, is_vehicle=is_vehicle, room_number=room_number)
+    room = Room(owner=owner, city=city, address=address, floor=floor, is_vehicle=is_vehicle, room_number=room_number)
     room.save()
     room.equipment.set(equipment)  # Cannot be made in constructor/with single save
     room.save()
@@ -392,14 +427,14 @@ def create_language(name="French", locale=DEFAULT_LOCALE_NAME) -> Language:
 
 
 def get_resource_path(filename):
-    return os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data', filename)
+    return os.path.join(os.path.dirname(os.path.realpath(__file__)), "data", filename)
 
 
 def format_form_field(value):
     if isinstance(value, datetime.date):
-        return value.strftime('%Y-%m-%d')
+        return value.strftime("%Y-%m-%d")
     elif isinstance(value, datetime.datetime):
-        return value.strftime('%Y-%m-%d %H:%M')
+        return value.strftime("%Y-%m-%d %H:%M")
     elif value is None:
         return ""
     else:
@@ -409,14 +444,12 @@ def format_form_field(value):
 def prepare_test_redcap_connection():
     Language.objects.create(name="Finnish").save()
     Language.objects.create(name="Italian").save()
-    token_item = ConfigurationItem.objects.filter(
-        type=REDCAP_TOKEN_CONFIGURATION_TYPE)[0]
+    token_item = ConfigurationItem.objects.filter(type=REDCAP_TOKEN_CONFIGURATION_TYPE)[0]
     # noinspection SpellCheckingInspection
-    token_item.value = "5DC21D45E3A2E068659F11046EA88734"
+    token_item.value = settings.REDCAP_TEST_API_TOKEN
     token_item.save()
-    url_item = ConfigurationItem.objects.filter(
-        type=REDCAP_BASE_URL_CONFIGURATION_TYPE)[0]
-    url_item.value = "https://luxparktest.lcsb.uni.lu/redcap/"
+    url_item = ConfigurationItem.objects.filter(type=REDCAP_BASE_URL_CONFIGURATION_TYPE)[0]
+    url_item.value = settings.REDCAP_TEST_URL
     url_item.save()
 
 
@@ -427,49 +460,68 @@ def datetimeify_date(date: Union[datetime.date, str, bytes]) -> datetime.datetim
         else:
             return make_aware(date)
     if isinstance(date, bytes):  # If it's bytes, then convert to string and carry on...
-        date = date.decode('utf8')
+        date = date.decode("utf8")
     if isinstance(date, str):  # If it's string, convert to datetime with timezone support
-        return make_aware(datetime.datetime.strptime(date, '%Y-%m-%d'))
+        return make_aware(datetime.datetime.strptime(date, "%Y-%m-%d"))
 
     actual_type = str(type(date))
     raise TypeError(
-        f"Date should be either a subclass of 'datetime.date', string or bytes! But is: {actual_type} instead")
+        f"Date should be either a subclass of 'datetime.date', string or bytes! But is: {actual_type} instead"
+    )
 
 
 def create_tns_column_mapping(subject_import_data: SubjectImportData):
-    EtlColumnMapping.objects.create(etl_data=subject_import_data,
-                                    column_name="nd_number",
-                                    csv_column_name="donor_id",
-                                    table_name=StudySubject._meta.db_table)
-    EtlColumnMapping.objects.create(etl_data=subject_import_data,
-                                    column_name="comments",
-                                    csv_column_name="treatingphysician",
-                                    table_name=StudySubject._meta.db_table)
-    EtlColumnMapping.objects.create(etl_data=subject_import_data,
-                                    column_name="first_name",
-                                    csv_column_name="firstname",
-                                    table_name=Subject._meta.db_table)
-    EtlColumnMapping.objects.create(etl_data=subject_import_data,
-                                    column_name="first_name",
-                                    csv_column_name="sig_firstname",
-                                    table_name=Subject._meta.db_table)
-    EtlColumnMapping.objects.create(etl_data=subject_import_data,
-                                    column_name="last_name",
-                                    csv_column_name="lastname",
-                                    table_name=Subject._meta.db_table)
-    EtlColumnMapping.objects.create(etl_data=subject_import_data,
-                                    column_name="last_name",
-                                    csv_column_name="sig_lastname",
-                                    table_name=Subject._meta.db_table)
-    EtlColumnMapping.objects.create(etl_data=subject_import_data,
-                                    column_name="phone_number",
-                                    csv_column_name="phonenr",
-                                    table_name=Subject._meta.db_table)
-    EtlColumnMapping.objects.create(etl_data=subject_import_data,
-                                    column_name="date_born",
-                                    csv_column_name="dateofbirth",
-                                    table_name=Subject._meta.db_table)
-    EtlColumnMapping.objects.create(etl_data=subject_import_data,
-                                    column_name="next_of_kin_name",
-                                    csv_column_name="representative",
-                                    table_name=Subject._meta.db_table)
+    EtlColumnMapping.objects.create(
+        etl_data=subject_import_data,
+        column_name="nd_number",
+        csv_column_name="donor_id",
+        table_name=StudySubject._meta.db_table,
+    )
+    EtlColumnMapping.objects.create(
+        etl_data=subject_import_data,
+        column_name="comments",
+        csv_column_name="treatingphysician",
+        table_name=StudySubject._meta.db_table,
+    )
+    EtlColumnMapping.objects.create(
+        etl_data=subject_import_data,
+        column_name="first_name",
+        csv_column_name="firstname",
+        table_name=Subject._meta.db_table,
+    )
+    EtlColumnMapping.objects.create(
+        etl_data=subject_import_data,
+        column_name="first_name",
+        csv_column_name="sig_firstname",
+        table_name=Subject._meta.db_table,
+    )
+    EtlColumnMapping.objects.create(
+        etl_data=subject_import_data,
+        column_name="last_name",
+        csv_column_name="lastname",
+        table_name=Subject._meta.db_table,
+    )
+    EtlColumnMapping.objects.create(
+        etl_data=subject_import_data,
+        column_name="last_name",
+        csv_column_name="sig_lastname",
+        table_name=Subject._meta.db_table,
+    )
+    EtlColumnMapping.objects.create(
+        etl_data=subject_import_data,
+        column_name="phone_number",
+        csv_column_name="phonenr",
+        table_name=Subject._meta.db_table,
+    )
+    EtlColumnMapping.objects.create(
+        etl_data=subject_import_data,
+        column_name="date_born",
+        csv_column_name="dateofbirth",
+        table_name=Subject._meta.db_table,
+    )
+    EtlColumnMapping.objects.create(
+        etl_data=subject_import_data,
+        column_name="next_of_kin_name",
+        csv_column_name="representative",
+        table_name=Subject._meta.db_table,
+    )
-- 
GitLab