Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Healthcheck, nginx fix, added tests for django #102

Merged
merged 15 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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