Skip to content

Commit

Permalink
feat: Healthcheck, nginx fix, added tests for django (#102)
Browse files Browse the repository at this point in the history
* nginx fix duplicate content type

* added healthcheck in docker-compose files

* removing old test files

* moved healthcheck to dockerfile for github security check pass

* added tests to django app

* added running django test for merge

* moved django test to pr-open action

* fixed path for manage.py

* invocing django test from within docker image

* fixed docker image name for django test

* removed test

---------

Co-authored-by: Derek Roberts <[email protected]>
  • Loading branch information
tobiasmllr and DerekRoberts authored Mar 18, 2024
1 parent 89dab7b commit a8ffeb1
Show file tree
Hide file tree
Showing 18 changed files with 252 additions and 394 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/merge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,4 @@ jobs:
overwrite: true
parameters:
-p ZONE=test -p PROMOTE=${{ github.repository }}/${{ matrix.name }}:test
-p NAME=${{ github.event.repository.name }}
-p NAME=${{ github.event.repository.name }}
5 changes: 5 additions & 0 deletions frontend/Dockerfile.app
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,12 @@ RUN chmod -R 777 /app
RUN useradd -m rctool
USER rctool


# copy project
COPY --from=BUILDER /venv /venv

# healthcheck
HEALTHCHECK --interval=60s --timeout=10s \
CMD python manage.py check

CMD ["sh", "-c", "/app/start_app.sh"]
8 changes: 7 additions & 1 deletion frontend/Dockerfile.nginx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ ENV PYTHONUNBUFFERED 1
ENV PATH="/venv/bin:$PATH"

RUN apt-get update --no-install-recommends && \
apt-get install -y gcc
apt-get install -y gcc
RUN python -m venv /venv

# install requirements
Expand Down Expand Up @@ -40,4 +40,10 @@ RUN touch /var/run/nginx.pid && \
chown -R nginx:nginx /var/run/nginx.pid && chmod -R 777 /var/run/nginx.pid

USER nginx


# healthcheck
HEALTHCHECK --interval=60s --timeout=10s \
CMD service nginx status

CMD ["sh", "-c", "/app/start_nginx.sh"]
1 change: 0 additions & 1 deletion frontend/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ http {
# allow csv files and pdf files to be served
types {
text/csv csv;
application/pdf pdf;
}

large_client_header_buffers 4 32k;
Expand Down
184 changes: 183 additions & 1 deletion frontend/rctool/tests.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,185 @@
from django.test import TestCase
from django.contrib.staticfiles import finders

# Create your tests here.
from django.urls import reverse

# import forms
from rctool.forms import import_rc_data, develop_rc, export_rc_data
import pandas as pd
import datetime as dt
from io import StringIO
import json


# Tests data import and export from sample_data.csv
class BaseTestCase(TestCase):
test_csv = finders.find("sample_data/sample_data.csv")

# test if the sample csv file exists
def test_sample_csv_exists(self):
assert self.test_csv is not None

def test_import_csv(self):
# read the csv file
with open(self.test_csv, "r") as file:
data = file.read()
assert data is not None
assert len(data) > 0

def test_import_rc_data_form(self):
# test the import form
self.form_data_import = {
"header_row": 1,
"csv_upload": open(self.test_csv, "rb"),
}
form_import = import_rc_data(data=self.form_data_import)
print(form_import.errors if form_import.errors else "form_import is valid")
assert form_import.is_valid()

# try to post the form data and check if the form submission is successful
response = self.client.post(
reverse("rctool_import", kwargs={"tour_request_id": 0}),
data=self.form_data_import,
follow=True,
)
# check if the form submission is successful
assert response.status_code == 200

# if form submission with sample data is successful, the table data should be populated
assert (
len(response.context["table_data"]) > 0
), "Table data is empty, sample form import failed"

# check if the raw field data is populated
raw_fielddata = response.context["raw_field_data"]
assert raw_fielddata is not None

df_fielddata = pd.read_json(StringIO(raw_fielddata))
df_fielddata["datetime"] = pd.to_datetime(df_fielddata["datetime"])
df_fielddata["datetime"] = df_fielddata["datetime"].dt.strftime(
"%Y-%m-%d %H:%M:%S"
)
return df_fielddata

# test if the develop rc form is valid and can be submitted successfully

def test_develop_rc_form(self):
self.form_data_develop = {
"set_offset1": 0,
"set_offset2": 0,
"set_breakpoint1": 0,
"set_breakpoint2": 0,
}

form_develop = develop_rc(data=self.form_data_develop)
print(form_develop.errors if form_develop.errors else "form_develop is valid")
assert form_develop.is_valid()

# load raw field data from the import form
df_fielddata = self.test_import_rc_data_form()
# set all field data to active
df_fielddata["active"] = "checked"

def col_to_string(lst, format=None):
values = lst.values.tolist()
values_list = []

for val in values:
if isinstance(val, str):
values_list.append(val)
elif isinstance(val, float):
values_list.append(str(val))

return ",".join(values_list)

# create post data for the develop rc form
post_data = {
"offset1": 0,
"offset2": 0,
"breakpoint1": 0,
"breakpoint2": 0,
"toggle_weighted_fit": "on",
"tour_request_status_id": 0,
"n-seg": 1,
"fieldData_datetime": col_to_string(df_fielddata["datetime"]),
"fieldData_comments": col_to_string(df_fielddata["comments"]),
"fieldData_uncertainty": col_to_string(df_fielddata["uncertainty"]),
"fieldData_stage": col_to_string(df_fielddata["stage"]),
"fieldData_discharge": col_to_string(df_fielddata["discharge"]),
"fieldData_active": col_to_string(df_fielddata["active"]),
"filename": "testexport.pdf",
}

# try to post the form data and check if the form submission is successful
response = self.client.post(
reverse("rctool_develop_autofit"),
data=post_data,
follow=True,
)

# check if the form submission is successful
assert response.status_code == 200

# test if a rating curve was successfully autofitted
rc_data = response.context["rc"]
assert rc_data is not None
assert len(rc_data) > 0

return rc_data

def test_export_rc_data_form(self):
self.form_data_export = {
"export_filetype": "session results (pdf)",
"export_filename": "testexport.pdf",
"export_station_name": "teststation",
"export_comments": "test comments",
"export_date_applic_init": "2024-01-01",
"export_date_applic_final": "2024-01-31",
}

# check if the import form is valid
form_export = export_rc_data(data=self.form_data_export)
print(form_export.errors if form_export.errors else "form_export is valid")
assert form_export.is_valid()

rc_data = self.test_develop_rc_form()
# try to post the form data and check if the form submission is successful
post_dict_initialize = {
"fieldData_datetime": "2024-01-01",
"fieldData_comments": "2024-01-02",
"fieldData_uncertainty": "1",
"fieldData_stage": "2",
"fieldData_discharge": "3",
"fieldData_active": "1",
"rc_out": json.dumps(rc_data),
"filename_out": "testexport.pdf",
}

response_initialize = self.client.post(
reverse("rctool_export_initialize"),
data=post_dict_initialize,
follow=True,
)
# # check if the form submission is successful
assert response_initialize.status_code == 200

df_fielddata = self.test_import_rc_data_form()
df_fielddata["toggle_point"] = "checked"
post_dict_output = {
"fielddatacsv-to-output": json.dumps(df_fielddata.to_dict()),
"rc_output": json.dumps(rc_data),
"export_filetype": "session results (pdf)",
"export_filename": "testexport.pdf",
"export_station_name": "teststation",
"export_comments": "test comments",
"export_date_applic_init": "2024-01-01",
"export_date_applic_final": "2024-01-31",
}
response_output = self.client.post(
reverse("rctool_export_output"),
data=post_dict_output,
follow=True,
)
# check if the output is a pdf:
assert response_output.status_code == 200
assert response_output["Content-Type"] == "application/pdf"
37 changes: 29 additions & 8 deletions frontend/rctool/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,34 @@
from . import views

urlpatterns = [
#path("", views.index, name="index"),
# path("", views.index, name="index"),
path("", views.home, name="home"),
path("about/", views.about, name="about"),
path("rctool/tour/<int:tour_request_id>/", views.rctool_tour_intro, name="rctool_tour_intro"),
path("rctool/import/<int:tour_request_id>/", views.rctool_import, name="rctool_import"),
path("rctool/develop/initialize", views.rctool_develop_initialize, name="rctool_develop_initialize"),
path("rctool/develop/", views.rctool_develop_autofit, name="rctool_develop_autofit"),
path("rctool/export/initialize", views.rctool_export_initialize, name="rctool_export_initialize"),
path("rctool/export/output", views.rctool_export_output, name="rctool_export_output"),
]
path(
"rctool/tour/<int:tour_request_id>/",
views.rctool_tour_intro,
name="rctool_tour_intro",
),
path(
"rctool/import/<int:tour_request_id>/",
views.rctool_import,
name="rctool_import",
),
path(
"rctool/develop/initialize",
views.rctool_develop_initialize,
name="rctool_develop_initialize",
),
path(
"rctool/develop/", views.rctool_develop_autofit, name="rctool_develop_autofit"
),
path(
"rctool/export/initialize",
views.rctool_export_initialize,
name="rctool_export_initialize",
),
path(
"rctool/export/output", views.rctool_export_output, name="rctool_export_output"
),
path("healthcheck/", views.healthcheck, name="healthcheck"),
]
Loading

0 comments on commit a8ffeb1

Please sign in to comment.