LiveTest register device

This commit is contained in:
Tom Irgang 2023-04-25 11:06:31 +02:00
parent f852a89e8a
commit 904d009fc9
13 changed files with 213 additions and 68 deletions

View file

@ -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`

View file

@ -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)

View file

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 572 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 933 KiB

View 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
View 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)

View file

@ -1,9 +1,9 @@
{% extends "repapp/base.html" %}
{% block title %}
- Repair-Cafés
- Repair-Cafés
{% endblock title %}
{% block head %}
<style>
<style>
@font-face {
font-family:'Source Sans Pro';
font-style:normal;
@ -280,45 +280,45 @@
color: #ffffff!important;
}
}
</style>
</style>
{% endblock head %}
{% block content %}
<h1 class="mt-2">Repair-Cafés</h1>
<hr class="mt-0 mb-4">
<ul class="list-group">
{% for cafe in object_list %}
<li class="list-group-item">
<div class="news-list-view eventhome snipcss-aSNzE" id="news-container-82">
<div class="rc-date">
<div class="article event rc-date "
itemscope="itemscope"
itemtype="http://schema.org/Article">
<div class="dtdate">
<time itemprop="datePublished" datetime="13.05.2023">
{{ cafe.event_date|date:"l" }}, {{ cafe.event_date|date }}, 14.00 - 17.00 Uhr
</time>
</div>
<div class="ort">
{{ cafe.location }}
<br>
{{ cafe.address }}
</div>
<div class="teaser-text">
<div itemprop="description">
<p>
<strong>
Nur per Voranmeldung.
<a href="{% url 'register_device' cafe.id %}">Zum Anmeldeformular</a>
</strong>
</p>
</div>
</div>
</div>
</div>
<h1 class="mt-2">Repair-Cafés</h1>
<hr class="mt-0 mb-4">
<ul class="list-group">
{% for cafe in object_list %}
<li class="list-group-item">
<div class="news-list-view eventhome snipcss-aSNzE" id="news-container-82">
<div class="rc-date">
<div class="article event rc-date "
itemscope="itemscope"
itemtype="http://schema.org/Article">
<div class="dtdate">
<time itemprop="datePublished" datetime="13.05.2023">
{{ cafe.event_date|date:"l" }}, {{ cafe.event_date|date }}, 14.00 - 17.00 Uhr
</time>
</div>
<div class="ort">
{{ cafe.location }}
<br>
{{ cafe.address }}
</div>
<div class="teaser-text">
<div itemprop="description">
<p>
<strong>
Nur per Voranmeldung.
<a class="register_link" href="{% url 'register_device' cafe.id %}">Zum Anmeldeformular</a>
</strong>
</p>
</div>
</li>
{% empty %}
<li class="list-group-item">Es gibt keine geplanten Repair-Cafés.</li>
{% endfor %}
</ul>
</div>
</div>
</div>
</div>
</li>
{% empty %}
<li class="list-group-item">Es gibt keine geplanten Repair-Cafés.</li>
{% endfor %}
</ul>
{% endblock content %}

View file

@ -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 %}

View file

@ -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">
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="btn btn-primary">Absenden</button>
</form>
<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 submit_button">Absenden</button>
</form>
{% endblock content %}

View file

@ -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

View file

@ -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(

View file

@ -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