LiveTest register device
This commit is contained in:
parent
f852a89e8a
commit
904d009fc9
13 changed files with 213 additions and 68 deletions
24
README.md
24
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`
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
BIN
rc_hip/repapp/fixtures/Hummingbird.jpg
Normal file
BIN
rc_hip/repapp/fixtures/Hummingbird.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 572 KiB |
BIN
rc_hip/repapp/fixtures/Nut.jpg
Normal file
BIN
rc_hip/repapp/fixtures/Nut.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 933 KiB |
11
rc_hip/repapp/fixtures/cafe-data.json
Normal file
11
rc_hip/repapp/fixtures/cafe-data.json
Normal file
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
]
|
||||
112
rc_hip/repapp/live_tests.py
Normal file
112
rc_hip/repapp/live_tests.py
Normal file
|
|
@ -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)
|
||||
|
|
@ -308,7 +308,7 @@
|
|||
<p>
|
||||
<strong>
|
||||
Nur per Voranmeldung.
|
||||
<a href="{% url 'register_device' cafe.id %}">Zum Anmeldeformular</a>
|
||||
<a class="register_link" href="{% url 'register_device' cafe.id %}">Zum Anmeldeformular</a>
|
||||
</strong>
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,6 @@
|
|||
enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<button type="submit" class="btn btn-primary">Absenden</button>
|
||||
<button type="submit" class="btn btn-primary submit_button">Absenden</button>
|
||||
</form>
|
||||
{% endblock content %}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{% extends "repapp/base.html" %}
|
||||
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block title %}- Gast anmelden{% endblock title %}
|
||||
|
||||
{% block title %}
|
||||
- Gast anmelden
|
||||
{% endblock title %}
|
||||
{% block content %}
|
||||
<h1 class="mt-2">Ihre Daten</h1>
|
||||
<hr class="mt-0 mb-4">
|
||||
<form action="{% url 'register_guest' cafe.id device.identifier mail %}" method="post">
|
||||
<h1 class="mt-2">Ihre Daten</h1>
|
||||
<hr class="mt-0 mb-4">
|
||||
<form action="{% url 'register_guest' cafe.id device.identifier mail %}"
|
||||
method="post">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<button type="submit" class="btn btn-primary">Absenden</button>
|
||||
</form>
|
||||
<button type="submit" class="btn btn-primary submit_button">Absenden</button>
|
||||
</form>
|
||||
{% endblock content %}
|
||||
|
|
@ -3,9 +3,11 @@ Tests for RepApp.
|
|||
"""
|
||||
from datetime import datetime, timedelta
|
||||
import django.utils.timezone
|
||||
|
||||
from django.test import TestCase
|
||||
from django.test import Client
|
||||
from django.urls import reverse
|
||||
|
||||
from .backends import OneTimeLoginBackend, EmailBackend
|
||||
from .models import OneTimeLogin, CustomUser, Cafe
|
||||
|
||||
|
|
|
|||
|
|
@ -65,23 +65,17 @@ class RegisterDeviceFormView(generic.edit.FormView):
|
|||
|
||||
guest = Guest.objects.filter(mail=mail).first()
|
||||
|
||||
print(f'Register: Dev: {device}, Guest: {guest}')
|
||||
|
||||
if guest:
|
||||
print('Guest already known')
|
||||
device.guest = guest
|
||||
device.save()
|
||||
|
||||
send_confirmation_mails(device, guest, cafe, self.request)
|
||||
|
||||
print('Mails sent')
|
||||
|
||||
resp = HttpResponseRedirect(
|
||||
reverse_lazy('register_device_final', kwargs={
|
||||
'cafe': cafe.pk,
|
||||
'device_identifier': device.identifier})
|
||||
)
|
||||
print(resp)
|
||||
return resp
|
||||
else:
|
||||
return HttpResponseRedirect(
|
||||
|
|
|
|||
|
|
@ -9,3 +9,4 @@ crispy-bootstrap4==2022.1
|
|||
mozilla-django-oidc==3.0.0
|
||||
djlint==1.23.3
|
||||
django-import-export==3.2.0
|
||||
selenium==4.9.0
|
||||
|
|
|
|||
Reference in a new issue