diff --git a/src/tests/base/__init__.py b/src/tests/base/__init__.py index f72f5d583..e7d30fec0 100644 --- a/src/tests/base/__init__.py +++ b/src/tests/base/__init__.py @@ -2,8 +2,10 @@ import os import sys import time +from bs4 import BeautifulSoup from django.conf import settings from django.contrib.staticfiles.testing import StaticLiveServerTestCase +from django.test import TestCase from selenium import webdriver # could use Chrome, Firefox, etc... here @@ -39,3 +41,66 @@ class BrowserTest(StaticLiveServerTestCase): self.scroll_into_view(element) time.sleep(0.5) element.click() + + +class SoupTest(TestCase): + + def get_doc(self, *args, **kwargs): + response = self.client.get(*args, **kwargs) + return BeautifulSoup(response.rendered_content) + + def post_doc(self, *args, **kwargs): + kwargs['follow'] = True + response = self.client.post(*args, **kwargs) + return BeautifulSoup(response.rendered_content) + + +def extract_form_fields(soup): + """ + Turn a BeautifulSoup form in to a dict of fields and default values + Inspiration: https://gist.github.com/simonw/104413 + """ + data = {} + for field in soup.find_all('input'): + # ignore submit/image with no name attribute + if field['type'] in ('submit', 'image') and not field.has_attr('name'): + continue + + if field['type'] in ('checkbox', 'radio'): + if field.has_attr('checked'): + data[field['name']] = field.get('value', 'on') + + continue + else: + # single element name/value fields + data[field['name']] = field.get('value', '') + continue + + # textareas + for textarea in soup.findAll('textarea'): + data[textarea['name']] = textarea.string or '' + + # select fields + for select in soup.find_all('select'): + value = '' + options = select.find_all('option') + is_multiple = select.has_attr('multiple') + selected_options = [ + option for option in options + if option.has_attr('selected') + ] + + # If no select options, go with the first one + if not selected_options and options: + selected_options = [options[0]] + + if not is_multiple: + assert (len(selected_options) < 2) + if len(selected_options) == 1: + value = selected_options[0]['value'] + else: + value = [option['value'] for option in selected_options] + + data[select['name']] = value + + return data diff --git a/src/tests/control/test_auth.py b/src/tests/control/test_auth.py index 64bd82d38..5a40404b6 100644 --- a/src/tests/control/test_auth.py +++ b/src/tests/control/test_auth.py @@ -6,38 +6,10 @@ from django.contrib.auth.tokens import ( ) from django.core import mail as djmail from django.test import TestCase -from tests.base import BrowserTest from pretix.base.models import User -class LoginFormBrowserTest(BrowserTest): - - def setUp(self): - super().setUp() - self.user = User.objects.create_user('dummy@dummy.dummy', 'dummy') - - def test_login(self): - self.driver.implicitly_wait(10) - self.driver.get('%s%s' % (self.live_server_url, '/control/login')) - username_input = self.driver.find_element_by_name("email") - username_input.send_keys('dummy@dummy.dummy') - password_input = self.driver.find_element_by_name("password") - password_input.send_keys('dummy') - self.driver.find_element_by_css_selector('button[type="submit"]').click() - self.driver.find_element_by_class_name("navbar-right") - - def test_login_fail(self): - self.driver.implicitly_wait(10) - self.driver.get('%s%s' % (self.live_server_url, '/control/login')) - username_input = self.driver.find_element_by_name("email") - username_input.send_keys('dummy@dummy.dummy') - password_input = self.driver.find_element_by_name("password") - password_input.send_keys('wrong') - self.driver.find_element_by_css_selector('button[type="submit"]').click() - self.driver.find_element_by_class_name("alert-danger") - - class LoginFormTest(TestCase): def setUp(self): diff --git a/src/tests/control/test_events.py b/src/tests/control/test_events.py index 77dde321b..240460e70 100644 --- a/src/tests/control/test_events.py +++ b/src/tests/control/test_events.py @@ -1,13 +1,13 @@ import datetime -from tests.base import BrowserTest +from tests.base import SoupTest, extract_form_fields from pretix.base.models import ( Event, EventPermission, Organizer, OrganizerPermission, User, ) -class EventsTest(BrowserTest): +class EventsTest(SoupTest): def setUp(self): super().setUp() @@ -29,39 +29,37 @@ class EventsTest(BrowserTest): OrganizerPermission.objects.create(organizer=self.orga1, user=self.user) EventPermission.objects.create(event=self.event1, user=self.user, can_change_items=True, can_change_settings=True) - self.driver.implicitly_wait(10) - self.driver.get('%s%s' % (self.live_server_url, '/control/login')) - username_input = self.driver.find_element_by_name("email") - username_input.send_keys('dummy@dummy.dummy') - password_input = self.driver.find_element_by_name("password") - password_input.send_keys('dummy') - self.driver.find_element_by_css_selector('button[type="submit"]').click() - self.driver.find_element_by_class_name("navbar-right") + self.client.login(email='dummy@dummy.dummy', password='dummy') def test_event_list(self): - self.driver.get('%s%s' % (self.live_server_url, '/control/events/')) - tabletext = self.driver.find_element_by_css_selector("#page-wrapper .table").text + doc = self.get_doc('/control/events/') + tabletext = doc.select("#page-wrapper .table")[0].text self.assertIn("30C3", tabletext) self.assertNotIn("31C3", tabletext) self.assertNotIn("MRMCD14", tabletext) def test_settings(self): - self.driver.get('%s/control/event/%s/%s/settings/' % (self.live_server_url, self.orga1.slug, - self.event1.slug)) - self.driver.find_element_by_name("date_to").send_keys("2013-12-30 17:00:00") - self.driver.find_element_by_name("settings-max_items_per_order").clear() - self.driver.find_element_by_name("settings-max_items_per_order").send_keys("12") - self.driver.find_element_by_class_name("btn-save").click() - self.driver.find_element_by_class_name("alert-success") - self.assertIn("2013-12-30 17:00:00", self.driver.find_element_by_name("date_to").get_attribute("value")) - self.assertIn("12", self.driver.find_element_by_name("settings-max_items_per_order").get_attribute("value")) + doc = self.get_doc('/control/event/%s/%s/settings/' % (self.orga1.slug, self.event1.slug)) + doc.select("[name=date_to]")[0]['value'] = "2013-12-30 17:00:00" + doc.select("[name=settings-max_items_per_order]")[0]['value'] = "12" + print(extract_form_fields(doc.select('.container-fluid form')[0])) + + doc = self.post_doc('/control/event/%s/%s/settings/' % (self.orga1.slug, self.event1.slug), + extract_form_fields(doc.select('.container-fluid form')[0])) + print(doc) + assert len(doc.select(".alert-success")) > 0 + assert doc.select("[name=date_to]")[0]['value'] == "2013-12-30 17:00:00" + assert doc.select("[name=settings-max_items_per_order]")[0]['value'] == "12" def test_plugins(self): - self.driver.get('%s/control/event/%s/%s/settings/plugins' % (self.live_server_url, self.orga1.slug, - self.event1.slug)) - self.assertIn("Bank transfer", self.driver.find_element_by_class_name("form-plugins").text) - self.assertIn("Enable", self.driver.find_element_by_name("plugin:pretix.plugins.banktransfer").text) - self.driver.find_element_by_name("plugin:pretix.plugins.banktransfer").click() - self.assertIn("Disable", self.driver.find_element_by_name("plugin:pretix.plugins.banktransfer").text) - self.driver.find_element_by_name("plugin:pretix.plugins.banktransfer").click() - self.assertIn("Enable", self.driver.find_element_by_name("plugin:pretix.plugins.banktransfer").text) + doc = self.get_doc('/control/event/%s/%s/settings/plugins' % (self.orga1.slug, self.event1.slug)) + self.assertIn("Bank transfer", doc.select(".form-plugins")[0].text) + self.assertIn("Enable", doc.select("[name=plugin:pretix.plugins.banktransfer]")[0].text) + + doc = self.post_doc('/control/event/%s/%s/settings/plugins' % (self.orga1.slug, self.event1.slug), + {'plugin:pretix.plugins.banktransfer': 'enable'}) + self.assertIn("Disable", doc.select("[name=plugin:pretix.plugins.banktransfer]")[0].text) + + doc = self.post_doc('/control/event/%s/%s/settings/plugins' % (self.orga1.slug, self.event1.slug), + {'plugin:pretix.plugins.banktransfer': 'disable'}) + self.assertIn("Enable", doc.select("[name=plugin:pretix.plugins.banktransfer]")[0].text) diff --git a/src/tests/presale/test_event.py b/src/tests/presale/test_event.py index d63d730ba..6066776e7 100644 --- a/src/tests/presale/test_event.py +++ b/src/tests/presale/test_event.py @@ -3,7 +3,7 @@ import time from django.test import TestCase from django.utils.timezone import now -from tests.base import BrowserTest +from tests.base import BrowserTest, SoupTest from pretix.base.models import ( Event, EventPermission, Item, ItemCategory, ItemVariation, Organizer, @@ -24,23 +24,22 @@ class EventTestMixin: EventPermission.objects.create(user=self.user, event=self.event) -class EventMiddlewareTest(EventTestMixin, BrowserTest): +class EventMiddlewareTest(EventTestMixin, SoupTest): def setUp(self): super().setUp() - self.driver.implicitly_wait(10) def test_event_header(self): - self.driver.get('%s/%s/%s/' % (self.live_server_url, self.orga.slug, self.event.slug)) - self.assertIn(str(self.event.name), self.driver.find_element_by_css_selector("h1").text) + doc = self.get_doc('/%s/%s/' % (self.orga.slug, self.event.slug)) + self.assertIn(str(self.event.name), doc.find("h1").text) def test_not_found(self): - resp = self.client.get('%s/%s/%s/' % (self.live_server_url, 'foo', 'bar')) + resp = self.client.get('/%s/%s/' % ('foo', 'bar')) self.assertEqual(resp.status_code, 404) def test_not_live(self): self.event.live = False self.event.save() - resp = self.client.get('%s/%s/%s/' % (self.live_server_url, self.orga.slug, self.event.slug)) + resp = self.client.get('/%s/%s/' % (self.orga.slug, self.event.slug)) self.assertEqual(resp.status_code, 403) def test_not_live_logged_in(self): @@ -48,7 +47,7 @@ class EventMiddlewareTest(EventTestMixin, BrowserTest): self.event.save() self.client.login(email='dummy@dummy.dummy', password='dummy') - resp = self.client.get('%s/%s/%s/' % (self.live_server_url, self.orga.slug, self.event.slug)) + resp = self.client.get('/%s/%s/' % (self.orga.slug, self.event.slug)) self.assertEqual(resp.status_code, 200)