- {{ cafe.address }} -
diff --git a/README.md b/README.md index cb98011..b001e40 100644 --- a/README.md +++ b/README.md @@ -7,13 +7,13 @@ For documentation see https://makes-hacks-hip.github.io/RepApp/. ## Setup for development - Clone repo -- python -m venv venv -- source venv/bin/activate -- cd rc_hip -- python manage.py makemigrations -- python manage.py migrate -- python manage.py createsuperuser -- python manage.py runserver +- `python -m venv venv` +- `source venv/bin/activate` +- `cd rc_hip` +- `python manage.py makemigrations` +- `python manage.py migrate` +- `python manage.py createsuperuser` +- `python manage.py runserver` ## Build Docker image @@ -30,3 +30,13 @@ docker run --rm -d \ repapp` ``` - Open `http://127.0.0.1:8020/` in your browser + +## Run tests + +### Unit tests + +Run `python manage.py test` + +### LiveServer Tests + +Run `python manage.py test repapp.live_tests.WorkflowTests` diff --git a/rc_hip/repapp/admin.py b/rc_hip/repapp/admin.py index 8580170..7eb2f34 100644 --- a/rc_hip/repapp/admin.py +++ b/rc_hip/repapp/admin.py @@ -8,6 +8,21 @@ from .models import (Organisator, Cafe, Question, Device, CustomUser, Reparateur, Appointment, Guest, Candidate, OneTimeLogin, Message) +class CafeResource(resources.ModelResource): + """ + Resource wrapper for Cafe model. + """ + class Meta: + """ + Meta data for resource model. + """ + model = Cafe + + @staticmethod + def get_display_name(): + return "Repair-Café" + + class GuestResource(resources.ModelResource): """ Resource wrapper for Guest model. @@ -93,17 +108,18 @@ class ExportAdmin(ImportExportModelAdmin, ExportActionMixin): QuestionResource, AppointmentResource, CandidateResource, + CafeResource, ] # Register all models of RepApp for the admin interface. admin.site.register(Organisator) -admin.site.register(Cafe) admin.site.register(Reparateur) admin.site.register(CustomUser) admin.site.register(OneTimeLogin) admin.site.register(Message) # Make the "data" models exportable. +admin.site.register(Cafe, ExportAdmin) admin.site.register(Question, ExportAdmin) admin.site.register(Guest, ExportAdmin) admin.site.register(Device, ExportAdmin) diff --git a/rc_hip/repapp/backends.py b/rc_hip/repapp/backends.py index 732b6fb..b8d6ddb 100644 --- a/rc_hip/repapp/backends.py +++ b/rc_hip/repapp/backends.py @@ -14,7 +14,6 @@ class OneTimeLoginBackend(ModelBackend): """ def authenticate(self, request, username=None, password=None, **kwargs): - print(f'authenticate {username}') login = OneTimeLogin.objects.filter(secret=username).first() if login: return login.user diff --git a/rc_hip/repapp/fixtures/Hummingbird.jpg b/rc_hip/repapp/fixtures/Hummingbird.jpg new file mode 100644 index 0000000..8cdf460 Binary files /dev/null and b/rc_hip/repapp/fixtures/Hummingbird.jpg differ diff --git a/rc_hip/repapp/fixtures/Nut.jpg b/rc_hip/repapp/fixtures/Nut.jpg new file mode 100644 index 0000000..7308ecf Binary files /dev/null and b/rc_hip/repapp/fixtures/Nut.jpg differ diff --git a/rc_hip/repapp/fixtures/cafe-data.json b/rc_hip/repapp/fixtures/cafe-data.json new file mode 100644 index 0000000..05a5e96 --- /dev/null +++ b/rc_hip/repapp/fixtures/cafe-data.json @@ -0,0 +1,11 @@ +[ + { + "model": "repapp.cafe", + "pk": 1, + "fields": { + "location": "Haus Einstein' (beim Gymnasium)", + "address": "Patersholzer Weg 19, Hilpoltstein", + "event_date": "2023-05-13" + } + } +] \ No newline at end of file diff --git a/rc_hip/repapp/live_tests.py b/rc_hip/repapp/live_tests.py new file mode 100644 index 0000000..1a3e0a3 --- /dev/null +++ b/rc_hip/repapp/live_tests.py @@ -0,0 +1,112 @@ +import time +import os +from pathlib import Path +from django.contrib.staticfiles.testing import StaticLiveServerTestCase +from selenium.webdriver.common.by import By +from selenium.webdriver.firefox.webdriver import WebDriver + + +class WorkflowTests(StaticLiveServerTestCase): + fixtures = ["cafe-data.json"] + + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.selenium = WebDriver() + cls.selenium.implicitly_wait(10) + + @classmethod + def tearDownClass(cls): + cls.selenium.quit() + super().tearDownClass() + + def test_register_device(self): + # Open landing page + self.selenium.get(f"{self.live_server_url}/") + # Click on a register link + self.selenium.find_element(By.CLASS_NAME, "register_link").click() + time.sleep(1) + # Enter new device + # Enter guest mail address + mail = self.selenium.find_element(By.NAME, "mail") + mail.send_keys("guest@example.com") + # Enter device + device = self.selenium.find_element(By.NAME, "device") + device.send_keys("A Test Device") + # Enter manufacturer + manufacturer = self.selenium.find_element(By.NAME, "manufacturer") + manufacturer.send_keys("A Test Manufacturer") + # Enter a error description + error = self.selenium.find_element(By.NAME, "error") + error.send_keys("A description of the issue\nof the device.") + # Skip device picture and device type plate + # No follow up repair + # Accept repair conditions + self.selenium.find_element(By.NAME, "confirm_repair").click() + # Accept data protection notice + self.selenium.find_element(By.NAME, "confirm_data").click() + time.sleep(1) + # Send form + self.selenium.find_element(By.CLASS_NAME, 'submit_button').click() + time.sleep(1) + # Register new guest + # Enter guest name + name = self.selenium.find_element(By.NAME, "name") + name.send_keys("A Guest") + # Enter guest phone + phone = self.selenium.find_element(By.NAME, "phone") + phone.send_keys("0911 123 456") + # Enter guest residence + residence = self.selenium.find_element(By.NAME, "residence") + residence.send_keys("Musterstadt") + time.sleep(1) + # Send form + self.selenium.find_element(By.CLASS_NAME, 'submit_button').click() + time.sleep(1) + self.assertTrue("confirm" in self.selenium.current_url) + self.assertTrue("Anmeldung erfolgreich!" in self.selenium.page_source) + # Register second device + # Open landing page again + self.selenium.get(f"{self.live_server_url}/") + # Click on a register link + self.selenium.find_element(By.CLASS_NAME, "register_link").click() + time.sleep(1) + # Enter new device + # Enter guest mail address + mail = self.selenium.find_element(By.NAME, "mail") + mail.send_keys("guest@example.com") + # Enter device + device = self.selenium.find_element(By.NAME, "device") + device.send_keys("Another Test Device") + # Enter manufacturer + manufacturer = self.selenium.find_element(By.NAME, "manufacturer") + manufacturer.send_keys("Another Test Manufacturer") + # Enter a error description + error = self.selenium.find_element(By.NAME, "error") + error.send_keys("Another issue description.") + # Add device picture + test_script_folder = Path(__file__).resolve().parent + fixtures_folder = os.path.join(test_script_folder, "fixtures") + device_picture_file = os.path.join(fixtures_folder, "Hummingbird.jpg") + device_picture = self.selenium.find_element(By.NAME, "device_picture") + device_picture.send_keys(device_picture_file) + print(f"Using device picture {device_picture_file}") + # Add type plate picture + type_plate_picture_file = os.path.join(fixtures_folder, "Nut.jpg") + type_plate_picture = self.selenium.find_element( + By.NAME, "type_plate_picture") + type_plate_picture.send_keys(type_plate_picture_file) + print(f"Using type plate picture {type_plate_picture_file}") + # Select as follow up repair + self.selenium.find_element(By.NAME, "follow_up").click() + # Accept repair conditions + self.selenium.find_element(By.NAME, "confirm_repair").click() + # Accept data protection notice + self.selenium.find_element(By.NAME, "confirm_data").click() + time.sleep(1) + # Send form + self.selenium.find_element(By.CLASS_NAME, 'submit_button').click() + time.sleep(1) + # Guest is known, no guest registration needed. + self.assertTrue("confirm" in self.selenium.current_url) + self.assertTrue("Anmeldung erfolgreich!" in self.selenium.page_source) diff --git a/rc_hip/repapp/templates/repapp/index.html b/rc_hip/repapp/templates/repapp/index.html index 07d63d7..44bf095 100644 --- a/rc_hip/repapp/templates/repapp/index.html +++ b/rc_hip/repapp/templates/repapp/index.html @@ -1,9 +1,9 @@ {% extends "repapp/base.html" %} {% block title %} - - Repair-Cafés + - Repair-Cafés {% endblock title %} {% block head %} - + {% endblock head %} {% block content %} -