From f70421b8cad79a654caeca63de4f157ac0f07df1 Mon Sep 17 00:00:00 2001 From: FreneticScribbler Date: Wed, 30 Sep 2020 09:08:20 +0100 Subject: [PATCH] Fix tests --- RIGS/tests/pages.py | 4 + RIGS/tests/test_functional.py | 865 +-------------------------------- RIGS/tests/test_interaction.py | 859 ++++++++++++++++++++++++++++++++ RIGS/tests/test_unit.py | 9 +- 4 files changed, 879 insertions(+), 858 deletions(-) create mode 100644 RIGS/tests/test_interaction.py diff --git a/RIGS/tests/pages.py b/RIGS/tests/pages.py index c5b6562b..a7c98fa6 100644 --- a/RIGS/tests/pages.py +++ b/RIGS/tests/pages.py @@ -271,6 +271,10 @@ class CreateEventChecklist(FormPage): def add_crew(self): self.find_element(*self._add_crew_locator).click() + @property + def bottom(self): + return self.find_element(*self._submit_locator) + @property def power_mic(self): return regions.BootstrapSelectElement(self, self.find_element(*self._power_mic_selector)) diff --git a/RIGS/tests/test_functional.py b/RIGS/tests/test_functional.py index 442614ec..fdd6b03e 100644 --- a/RIGS/tests/test_functional.py +++ b/RIGS/tests/test_functional.py @@ -1,262 +1,22 @@ -from . import pages -from django.core.management import call_command -from django.test import TestCase -from django.test.utils import override_settings -from django.urls import reverse -from urllib.parse import urlparse -from PyRIGS.tests.base import BaseTest, AutoLoginTest, screenshot_failure_cls -from RIGS import models, urls -from reversion import revisions as reversion -from selenium.webdriver.support import expected_conditions as EC -from selenium.webdriver.common.by import By -from selenium.webdriver.common.keys import Keys -from selenium.webdriver.support.ui import WebDriverWait -from PyRIGS.tests.base import animation_is_finished -from PyRIGS.tests import base -from PyRIGS.tests import regions as base_regions -from RIGS.tests import regions import datetime from datetime import date, time, timedelta -from django.utils import timezone -from selenium.webdriver.common.action_chains import ActionChains -from django.db import transaction -from django.test.client import Client -from django.core import mail, signing -from django.http import HttpResponseBadRequest +from urllib.parse import urlparse + from django.conf import settings -from selenium.common.exceptions import NoSuchElementException +from django.core import mail, signing +from django.core.management import call_command +from django.db import transaction +from django.http import HttpResponseBadRequest +from django.test import TestCase +from django.test.client import Client +from django.test.utils import override_settings +from django.urls import reverse +from django.utils import timezone +from reversion import revisions as reversion +from RIGS import models, urls +from RIGS.tests import regions - -@screenshot_failure_cls -class BaseRigboardTest(AutoLoginTest): - def setUp(self): - self.vatrate = models.VatRate.objects.create(start_at='2014-03-05', rate=0.20, comment='test1') - super().setUp() - self.client = models.Person.objects.create(name='Rigboard Test Person', email='rigboard@functional.test') - self.wait = WebDriverWait(self.driver, 10) - - def select_event_type(self, event_type): - self.wait.until(animation_is_finished()) - self.assertFalse(self.page.is_expanded) - self.page.select_event_type(event_type) - self.wait.until(animation_is_finished()) - self.assertTrue(self.page.is_expanded) - - -@screenshot_failure_cls -class TestRigboard(BaseRigboardTest): - def setUp(self): - super().setUp() - self.testEvent = models.Event.objects.create(name="TE E1", status=models.Event.PROVISIONAL, - start_date=date.today() + timedelta(days=6), - description="start future no end", - purchase_order='TESTPO', - person=self.client, - auth_request_by=self.profile, - auth_request_at=base.create_datetime(2015, 0o6, 0o4, 10, 00), - auth_request_to="some@email.address") - - item1 = models.EventItem( - event=self.testEvent, - name="Test Item 1", - cost="10.00", - quantity="1", - order=1 - ).save() - item2 = models.EventItem( - event=self.testEvent, - name="Test Item 2", - description="Foo", - cost="9.72", - quantity="3", - order=2, - ).save() - self.testEvent2 = models.Event.objects.create(name="TE E2", status=models.Event.PROVISIONAL, - start_date=date.today() + timedelta(days=8), - description="start future no end, later", - purchase_order='TESTPO', - person=self.client, - auth_request_by=self.profile, - auth_request_at=base.create_datetime(2015, 0o6, 0o4, 10, 00), - auth_request_to="some@email.address") - self.page = pages.Rigboard(self.driver, self.live_server_url).open() - - def test_buttons(self): - header = regions.Header(self.page, self.driver.find_element(By.CSS_SELECTOR, '.navbar')) - # TODO Switch to checking reversed links (difficult because of arguments) - header.find_link("Rigboard").click() - self.assertEqual( - self.live_server_url + '/rigboard/', self.driver.current_url) - header.find_link("Archive").click() - self.assertEqual( - self.live_server_url + '/event/archive/', self.driver.current_url) - # TODO - This fails for some reason - # header.find_link("New").click() - # self.assertEqual( - # self.live_server_url + '/event/create/', self.driver.current_url) - - def test_event_order(self): - self.assertIn(self.testEvent.start_date.strftime('%a %d/%m/%Y'), self.page.events[0].dates) - self.assertIn(self.testEvent2.start_date.strftime('%a %d/%m/%Y'), self.page.events[1].dates) - - def test_add_button(self): - self.page.add() - self.assertIn('create', self.driver.current_url) - # Ideally get a response object to assert 200 on - - -@screenshot_failure_cls -class TestEventCreate(BaseRigboardTest): - def setUp(self): - super().setUp() - self.page = pages.CreateEvent(self.driver, self.live_server_url).open() - - def test_rig_creation(self): - self.select_event_type("Rig") - - self.page.person_selector.search(self.client.name) - self.page.person_selector.set_option(self.client.name, True) - self.page.person_selector.toggle() - self.assertFalse(self.page.person_selector.is_open) - - self.page.name = "Test Rig" - - # Both dates, no times, end before start - self.page.start_date = datetime.date(2020, 1, 10) - self.page.end_date = datetime.date(2020, 1, 1) - # Expected to fail - self.page.submit() - self.assertFalse(self.page.success) - self.assertIn("Unless you've invented time travel, the event can't finish before it has started.", self.page.errors["End date"]) - self.wait.until(animation_is_finished()) - - self.page.access_at = datetime.datetime(2020, 1, 1, 9) - self.page.dry_hire = True - self.page.status = "Booked" - self.page.collected_by = "Fred" - self.page.po = "1234" - self.page.notes = "A note!" - - self.page.submit() - self.assertTrue(self.page.success) - - # TODO - def test_modals(self): - self.select_event_type("Rig") - # Create new person - modal = self.page.add_person() - # animation_is_finished doesn't work for whatever reason... - self.wait.until(EC.visibility_of_element_located((By.ID, 'modal'))) - self.assertTrue(modal.is_open) - self.assertIn("Add Person", modal.header) - - # Fill person form out and submit - person_name = "Test Person" - modal.name = person_name - modal.submit() - self.wait.until(EC.invisibility_of_element_located((By.ID, 'modal'))) - self.assertFalse(modal.is_open) - - # See new person selected - self.page.person_selector.toggle() - self.assertEqual(self.page.person_selector.options[0].name, person_name) - self.page.person_selector.toggle() - - # Change mind and add another - self.wait.until(animation_is_finished()) - modal = self.page.add_person() - self.wait.until(EC.visibility_of_element_located((By.ID, 'modal'))) - self.assertTrue(modal.is_open) - self.assertIn("Add Person", modal.header) - - person_name = "Test Person 2" - modal.name = person_name - modal.submit() - self.wait.until(EC.invisibility_of_element_located((By.ID, 'modal'))) - self.assertFalse(modal.is_open) - self.page.person_selector.toggle() - self.assertEqual(self.page.person_selector.options[0].name, person_name) - self.page.person_selector.toggle() - - # TODO - - def test_event_item_creation(self): - self.select_event_type("Rig") - - self.page.name = "Test Event with Items" - - self.page.person_selector.search(self.client.name) - self.page.person_selector.set_option(self.client.name, True) - # TODO This should not be necessary, normally closes automatically - self.page.person_selector.toggle() - self.assertFalse(self.page.person_selector.is_open) - - # Note to self, don't set dates before 2014, which is the beginning of VAT as far as the tests are concerned... - self.page.start_date = datetime.date(2084, 1, 1) - - modal = self.page.add_event_item() - self.wait.until(animation_is_finished()) - # See modal has opened - self.assertTrue(modal.is_open) - self.assertIn("New Event", modal.header) - - modal.name = "Test Item 1" - modal.description = "This is an item description\nthat for reasons unknown spans two lines" - modal.quantity = "2" - modal.price = "23.95" - modal.submit() - self.wait.until(animation_is_finished()) - - # Confirm item has been saved to json field - objectitems = self.driver.execute_script("return objectitems;") - self.assertEqual(1, len(objectitems)) - testitem = objectitems["-1"]['fields'] # as we are deliberately creating this we know the ID - self.assertEqual("Test Item 1", testitem['name']) - self.assertEqual("2", testitem['quantity']) # test a couple of "worse case" fields - - total = self.driver.find_element_by_id('total') - ActionChains(self.driver).move_to_element(total).perform() - - # See new item appear in table - row = self.page.item_row("-1") # ID number is known, see above - # Scroll into view - self.assertIn("Test Item 1", row.name) - self.assertIn("This is an item description", - row.description) - self.assertEqual('23.95', row.price) - self.assertEqual("2", row.quantity) - self.assertEqual('47.90', row.subtotal) - - # Check totals TODO convert to page properties - self.assertEqual("47.90", self.driver.find_element_by_id('sumtotal').text) - self.assertIn("(TBC)", self.driver.find_element_by_id('vat-rate').text) - self.assertEqual("9.58", self.driver.find_element_by_id('vat').text) - self.assertEqual("57.48", total.text) - - self.page.submit() - - # TODO Testing of internal rig (approval system interface) - - def test_non_rig_creation(self): - self.select_event_type("Non-Rig") - - self.assertFalse(self.page.person_selector.is_open) - - rig_name = "Test Non-Rig" - self.page.name = rig_name - - # Double-check we don't lose data when swapping - self.page.select_event_type("Rig") - self.wait.until(animation_is_finished()) - self.assertEquals(self.page.name, rig_name) - self.wait.until(animation_is_finished()) - self.page.select_event_type("Non-Rig") - - self.page.start_date = datetime.date(2020, 1, 1) - self.page.status = "Confirmed" - - self.page.submit() - self.assertTrue(self.page.success) +from . import pages class TestEventValidation(TestCase): @@ -278,390 +38,6 @@ class TestEventValidation(TestCase): self.assertFormError(response, 'form', 'access_at', "Regardless of what some clients might think, access time cannot be after the event has started.") -@screenshot_failure_cls -class TestEventDuplicate(BaseRigboardTest): - def setUp(self): - super().setUp() - self.testEvent = models.Event.objects.create(name="TE E1", status=models.Event.PROVISIONAL, - start_date=date.today() + timedelta(days=6), - description="start future no end", - purchase_order='TESTPO', - person=self.client, - auth_request_by=self.profile, - auth_request_at=base.create_datetime(2015, 0o6, 0o4, 10, 00), - auth_request_to="some@email.address") - - item1 = models.EventItem( - event=self.testEvent, - name="Test Item 1", - cost="10.00", - quantity="1", - order=1 - ).save() - item2 = models.EventItem( - event=self.testEvent, - name="Test Item 2", - description="Foo", - cost="9.72", - quantity="3", - order=2, - ).save() - self.page = pages.DuplicateEvent(self.driver, self.live_server_url, event_id=self.testEvent.pk).open() - - def test_rig_duplicate(self): - table = self.page.item_table - self.assertIn("Test Item 1", table.text) - self.assertIn("Test Item 2", table.text) - - # Check the info message is visible - self.assertIn("Event data duplicated but not yet saved", self.page.warning) - - modal = self.page.add_event_item() - self.wait.until(animation_is_finished()) - # See modal has opened - self.assertTrue(modal.is_open) - self.assertIn(self.testEvent.name, modal.header) - - modal.name = "Test Item 3" - modal.description = "This is an item description\nthat for reasons unknown spans two lines" - modal.quantity = "2" - modal.price = "23.95" - modal.submit() - self.wait.until(animation_is_finished()) - - # Attempt to save - self.page.submit() - - # TODO Rewrite when EventDetail page is implemented - newEvent = models.Event.objects.latest('pk') - - self.assertEqual(newEvent.auth_request_to, None) - self.assertEqual(newEvent.auth_request_by, None) - self.assertEqual(newEvent.auth_request_at, None) - - self.assertFalse(newEvent.authorised) - - self.assertNotIn("N%05d" % self.testEvent.pk, self.driver.find_element_by_xpath('//h1').text) - self.assertNotIn("Event data duplicated but not yet saved", self.page.warning) # Check info message not visible - - # Check the new items are visible - table = self.page.item_table - self.assertIn("Test Item 1", table.text) - self.assertIn("Test Item 2", table.text) - self.assertIn("Test Item 3", table.text) - - infoPanel = self.driver.find_element_by_xpath('//div[contains(text(), "Event Info")]/..') - self.assertIn("N%05d" % self.testEvent.pk, - infoPanel.find_element_by_xpath('//dt[text()="Based On"]/following-sibling::dd[1]').text) - # Check the PO hasn't carried through - self.assertNotIn("TESTPO", infoPanel.find_element_by_xpath('//dt[text()="PO"]/following-sibling::dd[1]').text) - - self.assertIn("N%05d" % self.testEvent.pk, - infoPanel.find_element_by_xpath('//dt[text()="Based On"]/following-sibling::dd[1]').text) - - self.driver.get(self.live_server_url + '/event/' + str(self.testEvent.pk)) # Go back to the old event - - # Check that based-on hasn't crept into the old event - infoPanel = self.driver.find_element_by_xpath('//div[contains(text(), "Event Info")]/..') - self.assertNotIn("N%05d" % self.testEvent.pk, - infoPanel.find_element_by_xpath('//dt[text()="Based On"]/following-sibling::dd[1]').text) - # Check the PO remains on the old event - self.assertIn("TESTPO", infoPanel.find_element_by_xpath('//dt[text()="PO"]/following-sibling::dd[1]').text) - - self.assertNotIn("N%05d" % self.testEvent.pk, - infoPanel.find_element_by_xpath('//dt[text()="Based On"]/following-sibling::dd[1]').text) - - # Check the items are as they were - table = self.page.item_table # ID number is known, see above - self.assertIn("Test Item 1", table.text) - self.assertIn("Test Item 2", table.text) - self.assertNotIn("Test Item 3", table.text) - - -@screenshot_failure_cls -class TestEventEdit(BaseRigboardTest): - def setUp(self): - super().setUp() - self.testEvent = models.Event.objects.create(name="TE E1", status=models.Event.PROVISIONAL, - start_date=date.today() + timedelta(days=6), - description="start future no end", - purchase_order='TESTPO', - person=self.client, - auth_request_by=self.profile, - auth_request_at=base.create_datetime(2015, 0o6, 0o4, 10, 00), - auth_request_to="some@email.address") - - item1 = models.EventItem( - event=self.testEvent, - name="Test Item 1", - cost="10.00", - quantity="1", - order=1 - ).save() - item2 = models.EventItem( - event=self.testEvent, - name="Test Item 2", - description="Foo", - cost="9.72", - quantity="3", - order=2, - ).save() - self.page = pages.EditEvent(self.driver, self.live_server_url, event_id=self.testEvent.pk).open() - - def test_rig_edit(self): - self.page.name = "Edited Event" - - modal = self.page.add_event_item() - self.wait.until(animation_is_finished()) - # See modal has opened - self.assertTrue(modal.is_open) - self.assertIn(self.testEvent.name, modal.header) - - modal.name = "Test Item 3" - modal.description = "This is an item description\nthat for reasons unknown spans two lines" - modal.quantity = "2" - modal.price = "23.95" - modal.submit() - self.wait.until(animation_is_finished()) - - # Attempt to save - ActionChains(self.driver).move_to_element(self.page.item_table).perform() - self.page.submit() - - self.assertTrue(self.page.success) - - self.page = pages.EventDetail(self.driver, self.live_server_url, event_id=self.testEvent.pk).open() - self.testEvent.refresh_from_db() - self.assertIn(self.testEvent.name, self.page.event_name) - self.assertEqual(self.page.name, self.testEvent.person.name) - # Check the new items are visible - table = self.page.item_table - self.assertIn("Test Item 3", table.text) - - -@screenshot_failure_cls -class TestEventDetail(BaseRigboardTest): - def setUp(self): - super().setUp() - self.testEvent = models.Event.objects.create(name="TE E1", status=models.Event.PROVISIONAL, - start_date=date.today() + timedelta(days=6), - description="start future no end", - purchase_order='TESTPO', - person=self.client, - auth_request_by=self.profile, - auth_request_at=base.create_datetime(2015, 0o6, 0o4, 10, 00), - auth_request_to="some@email.address") - - item1 = models.EventItem( - event=self.testEvent, - name="Test Item 1", - cost="10.00", - quantity="1", - order=1 - ).save() - item2 = models.EventItem( - event=self.testEvent, - name="Test Item 2", - description="Foo", - cost="9.72", - quantity="3", - order=2, - ).save() - self.page = pages.EventDetail(self.driver, self.live_server_url, event_id=self.testEvent.pk).open() - - def test_rig_detail(self): - self.assertIn("N%05d | %s" % (self.testEvent.pk, self.testEvent.name), self.page.event_name) - self.assertEqual(self.client.name, self.page.name) - self.assertEqual(self.client.email, self.page.email) - self.assertEqual(self.client.phone, None) - - -@screenshot_failure_cls -class TestCalendar(BaseRigboardTest): - def setUp(self): - super().setUp() - self.all_events = set(range(1, 18)) - self.current_events = (1, 2, 3, 6, 7, 8, 10, 11, 12, 14, 15, 16, 18) - self.not_current_events = set(self.all_events) - set(self.current_events) - - # produce 7 normal events - 5 current - 1 last week - 1 two years ago - 2 provisional - 2 confirmed - 3 booked - models.Event.objects.create(name="TE E1", status=models.Event.PROVISIONAL, - start_date=date.today() + timedelta(days=6), description="start future no end") - models.Event.objects.create(name="TE E2", status=models.Event.PROVISIONAL, start_date=date.today(), - description="start today no end") - models.Event.objects.create(name="TE E3", status=models.Event.CONFIRMED, start_date=date.today(), - end_date=date.today(), description="start today with end today") - models.Event.objects.create(name="TE E4", status=models.Event.CONFIRMED, - start_date=date.today() - timedelta(weeks=104), - description="start past 2 years no end") - models.Event.objects.create(name="TE E5", status=models.Event.BOOKED, - start_date=date.today() - timedelta(days=7), - end_date=date.today() - timedelta(days=1), - description="start past 1 week with end past") - models.Event.objects.create(name="TE E6", status=models.Event.BOOKED, - start_date=date.today() - timedelta(days=2), - start_time=time(8, 00), - end_date=date.today() + timedelta(days=2), - end_time=time(23, 00), description="start past, end future") - models.Event.objects.create(name="TE E7", status=models.Event.BOOKED, - start_date=date.today() + timedelta(days=2), - end_date=date.today() + timedelta(days=2), description="start + end in future") - - # 2 cancelled - 1 current - models.Event.objects.create(name="TE E8", start_date=date.today() + timedelta(days=2), - end_date=date.today() + timedelta(days=2), status=models.Event.CANCELLED, - description="cancelled in future") - models.Event.objects.create(name="TE E9", start_date=date.today() - timedelta(days=1), - end_date=date.today() + timedelta(days=2), status=models.Event.CANCELLED, - description="cancelled and started") - - # 5 dry hire - 3 current - 1 cancelled - models.Event.objects.create(name="TE E10", start_date=date.today(), dry_hire=True, description="dryhire today") - models.Event.objects.create(name="TE E11", start_date=date.today(), dry_hire=True, checked_in_by=self.profile, - description="dryhire today, checked in") - models.Event.objects.create(name="TE E12", start_date=date.today() - timedelta(days=1), dry_hire=True, - status=models.Event.BOOKED, description="dryhire past") - models.Event.objects.create(name="TE E13", start_date=date.today() - timedelta(days=2), dry_hire=True, - checked_in_by=self.profile, description="dryhire past checked in") - models.Event.objects.create(name="TE E14", start_date=date.today(), dry_hire=True, - status=models.Event.CANCELLED, description="dryhire today cancelled") - - # 4 non rig - 3 current - models.Event.objects.create(name="TE E15", start_date=date.today(), is_rig=False, description="non rig today") - models.Event.objects.create(name="TE E16", start_date=date.today() + timedelta(days=1), is_rig=False, - description="non rig tomorrow") - models.Event.objects.create(name="TE E17", start_date=date.today() - timedelta(days=1), is_rig=False, - description="non rig yesterday") - models.Event.objects.create(name="TE E18", start_date=date.today(), is_rig=False, status=models.Event.CANCELLED, - description="non rig today cancelled") - - self.page = pages.UserPage(self.driver, self.live_server_url).open() - - def test_api_key_generation(self): - # Completes and comes back to /user/ - # Checks that no api key is displayed - self.assertEqual("No API Key Generated", self.page.api_key) - - # Now creates an API key, and check a URL is displayed one - self.page.generate_key() - self.assertIn("rigs.ics", self.page.cal_url) - self.assertNotIn("?", self.page.cal_url) - - # Lets change everything so it's not the default value - self.page.toggle_filter('rig') - self.page.toggle_filter('non-rig') - self.page.toggle_filter('dry-hire') - self.page.toggle_filter('cancelled') - self.page.toggle_filter('provisional') - self.page.toggle_filter('confirmed') - - # and then check the url is correct - self.assertIn( - "rigs.ics?rig=false&non-rig=false&dry-hire=false&cancelled=true&provisional=false&confirmed=false", - self.page.cal_url) - - # Awesome - all seems to work - - def test_ics_files(self): - specialEvent = models.Event.objects.get(name="TE E6") - - # Now creates an API key, and check a URL is displayed one - self.page.generate_key() - - c = Client() - - # Default settings - should have all non-cancelled events - # Get the ical file (can't do this in selanium because reasons) - icalUrl = self.page.cal_url - response = c.get(self.page.cal_url) - self.assertEqual(200, response.status_code) - - # content = response.content.decode('utf-8') - - # Check has entire file - self.assertContains(response, "BEGIN:VCALENDAR") - self.assertContains(response, "END:VCALENDAR") - - expectedIn = [1, 2, 3, 5, 6, 7, 10, 11, 12, 13, 15, 16, 17] - for test in range(1, 18): - if test in expectedIn: - self.assertContains(response, "TE E" + str(test) + " ") - else: - self.assertNotContains(response, "TE E" + str(test) + " ") - - # Check that times have been included correctly - self.assertContains(response, - specialEvent.start_date.strftime('%Y%m%d') + 'T' + specialEvent.start_time.strftime( - '%H%M%S')) - self.assertContains(response, - specialEvent.end_date.strftime('%Y%m%d') + 'T' + specialEvent.end_time.strftime('%H%M%S')) - - # Only non rigs - self.page.toggle_filter('rig') - self.page.toggle_filter('non-rig') - - icalUrl = self.page.cal_url - response = c.get(icalUrl) - self.assertEqual(200, response.status_code) - - expectedIn = [10, 11, 12, 13] - for test in range(1, 18): - if test in expectedIn: - self.assertContains(response, "TE E" + str(test) + " ") - else: - self.assertNotContains(response, "TE E" + str(test) + " ") - - # Only provisional rigs - self.page.toggle_filter('rig') - self.page.toggle_filter('dry-hire') - self.page.toggle_filter('confirmed') - - icalUrl = self.page.cal_url - response = c.get(icalUrl) - self.assertEqual(200, response.status_code) - - expectedIn = [1, 2] - for test in range(1, 18): - if test in expectedIn: - self.assertContains(response, "TE E" + str(test) + " ") - else: - self.assertNotContains(response, "TE E" + str(test) + " ") - - # Only cancelled non-rigs - self.page.toggle_filter('rig') - self.page.toggle_filter('non-rig') - self.page.toggle_filter('provisional') - self.page.toggle_filter('cancelled') - - icalUrl = self.page.cal_url - response = c.get(icalUrl) - self.assertEqual(200, response.status_code) - - expectedIn = [18] - for test in range(1, 18): - if test in expectedIn: - self.assertContains(response, "TE E" + str(test) + " ") - else: - self.assertNotContains(response, "TE E" + str(test) + " ") - - # Nothing selected - self.page.toggle_filter('non-rig') - self.page.toggle_filter('cancelled') - - icalUrl = self.page.cal_url - response = c.get(icalUrl) - self.assertEqual(200, response.status_code) - - expectedIn = [] - for test in range(1, 18): - if test in expectedIn: - self.assertContains(response, "TE E" + str(test) + " ") - else: - self.assertNotContains(response, "TE E" + str(test) + " ") - - # Wow - that was a lot of tests - - class ClientEventAuthorisationTest(TestCase): auth_data = { 'name': 'Test ABC', @@ -811,214 +187,3 @@ class TECEventAuthorisationTest(TestCase): self.assertEqual(self.event.auth_request_by, self.profile) self.assertEqual(self.event.auth_request_to, 'client@functional.test') self.assertIsNotNone(self.event.auth_request_at) - - -@screenshot_failure_cls -class TestHealthAndSafety(BaseRigboardTest): - def setUp(self): - super().setUp() - self.profile = models.Profile.objects.get_or_create( - first_name='Test', - last_name='TEC User', - username='eventtest', - email='teccie@functional.test', - is_superuser=True # lazily grant all permissions - )[0] - self.testEvent = models.Event.objects.create(name="TE E1", status=models.Event.PROVISIONAL, - start_date=date.today() + timedelta(days=6), - description="start future no end", - purchase_order='TESTPO', - person=self.client) - self.page = pages.EventDetail(self.driver, self.live_server_url, event_id=self.testEvent.pk).open() - - # TODO Can I loop through all the boolean fields and test them at once? - def test_ra_creation(self): - self.page = pages.CreateRiskAssessment(self.driver, self.live_server_url, event_id=self.testEvent.pk).open() - - # Check there are no defaults - self.assertIsNone(self.page.nonstandard_equipment) - - # No database side validation, only HTML5. - - self.page.nonstandard_equipment = False - self.page.nonstandard_use = False - self.page.contractors = False - self.page.other_companies = False - self.page.crew_fatigue = False - self.page.general_notes = "There are no notes." - self.page.big_power = False - self.page.power_mic.search(self.profile.name) - self.page.power_mic.set_option(self.profile.name, True) - # TODO This should not be necessary, normally closes automatically - self.page.power_mic.toggle() - self.assertFalse(self.page.power_mic.is_open) - self.page.generators = False - self.page.other_companies_power = False - self.page.nonstandard_equipment_power = False - self.page.multiple_electrical_environments = False - self.page.power_notes = "Remember to bring some power" - self.page.noise_monitoring = False - self.page.sound_notes = "Loud, but not too loud" - self.page.known_venue = True - self.page.safe_loading = True - self.page.safe_storage = True - self.page.area_outside_of_control = False - self.page.barrier_required = False - self.page.nonstandard_emergency_procedure = False - self.page.special_structures = False - self.page.persons_responsible_structures = "Nobody and her cat, She" - self.page.suspended_structures = False - - self.page.submit() - self.assertTrue(self.page.success) - - # Test that we can't make another one - self.page = pages.CreateRiskAssessment(self.driver, self.live_server_url, event_id=self.testEvent.pk).open() - self.assertIn('edit', self.driver.current_url) - - def test_ra_edit(self): - # Create assessment to edit - self.page = pages.CreateRiskAssessment(self.driver, self.live_server_url, event_id=self.testEvent.pk).open() - self.page.nonstandard_equipment = False - self.page.nonstandard_use = False - self.page.contractors = False - self.page.other_companies = False - self.page.crew_fatigue = False - self.page.general_notes = "There are no notes." - self.page.big_power = False - self.page.power_mic.search(self.profile.name) - self.page.power_mic.toggle() - self.assertFalse(self.page.power_mic.is_open) - self.page.remove_all_required() - self.page.submit() - self.page = pages.EditRiskAssessment(self.driver, self.live_server_url, pk=models.RiskAssessment.objects.get(event=self.testEvent.pk).pk).open() - self.page.nonstandard_equipment = nse = True - self.page.general_notes = gn = "There are some notes, but I've not written them here as that would be helpful" - self.page.submit() - self.assertTrue(self.page.success) - # Check that data is right - ra = models.RiskAssessment.objects.get(event=self.testEvent.pk) - self.assertEqual(ra.general_notes, gn) - self.assertEqual(ra.nonstandard_equipment, nse) - - def test_ec_create_small(self): - self.page = pages.CreateEventChecklist(self.driver, self.live_server_url, event_id=self.testEvent.pk).open() - - self.page.safe_parking = True - self.page.safe_packing = True - self.page.exits = True - self.page.trip_hazard = True - self.page.warning_signs = True - self.page.ear_plugs = True - self.page.hs_location = "The Moon" - self.page.extinguishers_location = "With the rest of the fire" - # If we do this first the search fails, for ... reasons - self.page.power_mic.search(self.profile.name) - self.page.power_mic.toggle() - self.assertFalse(self.page.power_mic.is_open) - - self.page.select_size('Small') - self.wait.until(animation_is_finished()) - self.assertFalse(self.driver.find_element(By.XPATH, '(//*[@id="id_earthing"])[2]').is_displayed()) - self.assertTrue(self.driver.find_element(By.XPATH, '(//*[@id="id_earthing"])[1]').is_displayed()) - self.page.earthing = True - self.page.rcds = True - self.page.supply_test = True - self.page.pat = True - - self.page.submit() - self.assertTrue(self.page.success) - - def test_ec_create_medium(self): - self.page = pages.CreateEventChecklist(self.driver, self.live_server_url, event_id=self.testEvent.pk).open() - - self.page.safe_parking = True - self.page.safe_packing = True - self.page.exits = True - self.page.trip_hazard = True - self.page.warning_signs = True - self.page.ear_plugs = True - self.page.hs_location = "Death Valley" - self.page.extinguishers_location = "With the rest of the fire" - # If we do this first the search fails, for ... reasons - self.page.power_mic.search(self.profile.name) - self.page.power_mic.toggle() - self.assertFalse(self.page.power_mic.is_open) - - self.page.select_size('Medium') - self.wait.until(animation_is_finished()) - self.assertFalse(self.driver.find_element(By.XPATH, '(//*[@id="id_earthing"])[1]').is_displayed()) - self.assertTrue(self.driver.find_element(By.XPATH, '(//*[@id="id_earthing"])[2]').is_displayed()) - self.page.earthing_m = True - self.page.pat_m = True - self.page.source_rcd = True - self.page.labelling = True - self.page.fd_voltage_l1 = 240 - self.page.fd_voltage_l2 = 235 - self.page.fd_voltage_l3 = 0 - self.page.fd_phase_rotation = True - self.page.fd_earth_fault = 666 - self.page.fd_pssc = 1984 - self.page.w1_description = "In the carpark, by the bins" - self.page.w1_polarity = True - self.page.w1_voltage = 240 - self.page.w1_earth_fault = 333 - - self.page.submit() - self.assertTrue(self.page.success) - - def test_ec_create_extras(self): - self.page = pages.CreateEventChecklist(self.driver, self.live_server_url, event_id=self.testEvent.pk).open() - self.page.add_vehicle() - self.page.add_crew() - - self.page.safe_parking = True - self.page.safe_packing = True - self.page.exits = True - self.page.trip_hazard = True - self.page.warning_signs = True - self.page.ear_plugs = True - self.page.hs_location = "The Moon" - self.page.extinguishers_location = "With the rest of the fire" - # If we do this first the search fails, for ... reasons - self.page.power_mic.search(self.profile.name) - self.page.power_mic.toggle() - self.assertFalse(self.page.power_mic.is_open) - - vehicle_name = 'Brian' - self.driver.find_element(By.XPATH, '//*[@name="vehicle_-1"]').send_keys(vehicle_name) - driver = base_regions.BootstrapSelectElement(self.page, self.driver.find_element(By.XPATH, '(//*[contains(@class,"bootstrap-select")])[2]')) - driver.search(self.profile.name) - driver.toggle() - - crew = self.profile - role = "MIC" - crew_select = base_regions.BootstrapSelectElement(self.page, self.driver.find_element(By.XPATH, '(//*[contains(@class,"bootstrap-select")])[3]')) - start_time = base_regions.DateTimePicker(self.page, self.driver.find_element(By.XPATH, '//*[@name="start_-1"]')) - end_time = base_regions.DateTimePicker(self.page, self.driver.find_element(By.XPATH, '//*[@name="end_-1"]')) - - start_time.set_value(timezone.make_aware(datetime.datetime(2015, 1, 1, 9, 0))) - # TODO Validation of end before start - end_time.set_value(timezone.make_aware(datetime.datetime(2015, 1, 1, 10, 30))) - crew_select.search(crew.name) - crew_select.toggle() - self.driver.find_element(By.XPATH, '//*[@name="role_-1"]').send_keys(role) - - self.page.select_size('Small') - self.wait.until(animation_is_finished()) - self.assertFalse(self.driver.find_element(By.XPATH, '(//*[@id="id_earthing"])[2]').is_displayed()) - self.assertTrue(self.driver.find_element(By.XPATH, '(//*[@id="id_earthing"])[1]').is_displayed()) - self.page.earthing = True - self.page.rcds = True - self.page.supply_test = True - self.page.pat = True - - self.page.submit() - self.assertTrue(self.page.success) - - checklist = models.EventChecklist.objects.get(event=self.testEvent.pk) - vehicle = models.EventChecklistVehicle.objects.get(checklist=checklist.pk) - self.assertEqual(vehicle_name, vehicle.vehicle) - crew_obj = models.EventChecklistCrew.objects.get(checklist=checklist.pk) - self.assertEqual(crew.pk, crew_obj.crewmember.pk) - self.assertEqual(role, crew_obj.role) diff --git a/RIGS/tests/test_interaction.py b/RIGS/tests/test_interaction.py new file mode 100644 index 00000000..d19ecd3e --- /dev/null +++ b/RIGS/tests/test_interaction.py @@ -0,0 +1,859 @@ +import datetime +from datetime import date, time, timedelta +from urllib.parse import urlparse + +from django.conf import settings +from django.core import mail, signing +from django.core.management import call_command +from django.db import transaction +from django.http import HttpResponseBadRequest +from django.test.client import Client +from django.test.utils import override_settings +from django.urls import reverse +from django.utils import timezone +from PyRIGS.tests import base +from PyRIGS.tests import regions as base_regions +from PyRIGS.tests.base import (AutoLoginTest, BaseTest, animation_is_finished, + screenshot_failure_cls) +from reversion import revisions as reversion +from RIGS import models, urls +from RIGS.tests import regions +from selenium.common.exceptions import NoSuchElementException +from selenium.webdriver.common.action_chains import ActionChains +from selenium.webdriver.common.by import By +from selenium.webdriver.common.keys import Keys +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.common.action_chains import ActionChains + +from . import pages + + +@screenshot_failure_cls +class BaseRigboardTest(AutoLoginTest): + def setUp(self): + self.vatrate = models.VatRate.objects.create(start_at='2014-03-05', rate=0.20, comment='test1') + super().setUp() + self.client = models.Person.objects.create(name='Rigboard Test Person', email='rigboard@functional.test') + self.wait = WebDriverWait(self.driver, 10) + + def select_event_type(self, event_type): + self.wait.until(animation_is_finished()) + self.assertFalse(self.page.is_expanded) + self.page.select_event_type(event_type) + self.wait.until(animation_is_finished()) + self.assertTrue(self.page.is_expanded) + + +@screenshot_failure_cls +class TestRigboard(BaseRigboardTest): + def setUp(self): + super().setUp() + self.testEvent = models.Event.objects.create(name="TE E1", status=models.Event.PROVISIONAL, + start_date=date.today() + timedelta(days=6), + description="start future no end", + purchase_order='TESTPO', + person=self.client, + auth_request_by=self.profile, + auth_request_at=base.create_datetime(2015, 0o6, 0o4, 10, 00), + auth_request_to="some@email.address") + + item1 = models.EventItem( + event=self.testEvent, + name="Test Item 1", + cost="10.00", + quantity="1", + order=1 + ).save() + item2 = models.EventItem( + event=self.testEvent, + name="Test Item 2", + description="Foo", + cost="9.72", + quantity="3", + order=2, + ).save() + self.testEvent2 = models.Event.objects.create(name="TE E2", status=models.Event.PROVISIONAL, + start_date=date.today() + timedelta(days=8), + description="start future no end, later", + purchase_order='TESTPO', + person=self.client, + auth_request_by=self.profile, + auth_request_at=base.create_datetime(2015, 0o6, 0o4, 10, 00), + auth_request_to="some@email.address") + self.page = pages.Rigboard(self.driver, self.live_server_url).open() + + def test_buttons(self): + header = regions.Header(self.page, self.driver.find_element(By.CSS_SELECTOR, '.navbar')) + # TODO Switch to checking reversed links (difficult because of arguments) + header.find_link("Rigboard").click() + self.assertEqual( + self.live_server_url + '/rigboard/', self.driver.current_url) + header.find_link("Archive").click() + self.assertEqual( + self.live_server_url + '/event/archive/', self.driver.current_url) + # TODO - This fails for some reason + # header.find_link("New").click() + # self.assertEqual( + # self.live_server_url + '/event/create/', self.driver.current_url) + + def test_event_order(self): + self.assertIn(self.testEvent.start_date.strftime('%a %d/%m/%Y'), self.page.events[0].dates) + self.assertIn(self.testEvent2.start_date.strftime('%a %d/%m/%Y'), self.page.events[1].dates) + + def test_add_button(self): + self.page.add() + self.assertIn('create', self.driver.current_url) + # Ideally get a response object to assert 200 on + + +@screenshot_failure_cls +class TestEventCreate(BaseRigboardTest): + def setUp(self): + super().setUp() + self.page = pages.CreateEvent(self.driver, self.live_server_url).open() + + def test_rig_creation(self): + self.select_event_type("Rig") + + self.page.person_selector.search(self.client.name) + self.page.person_selector.set_option(self.client.name, True) + self.page.person_selector.toggle() + self.assertFalse(self.page.person_selector.is_open) + + self.page.name = "Test Rig" + + # Both dates, no times, end before start + self.page.start_date = datetime.date(2020, 1, 10) + self.page.end_date = datetime.date(2020, 1, 1) + # Expected to fail + self.page.submit() + self.assertFalse(self.page.success) + self.assertIn("Unless you've invented time travel, the event can't finish before it has started.", self.page.errors["End date"]) + self.wait.until(animation_is_finished()) + + # Fix it + self.page.end_date = datetime.date(2020, 1, 11) + self.page.access_at = datetime.datetime(2020, 1, 1, 9) + self.page.dry_hire = True + self.page.status = "Booked" + self.page.collected_by = "Fred" + self.page.po = "1234" + self.page.notes = "A note!" + + self.page.submit() + self.assertTrue(self.page.success) + + # TODO + def test_modals(self): + self.select_event_type("Rig") + # Create new person + modal = self.page.add_person() + # animation_is_finished doesn't work for whatever reason... + self.wait.until(EC.visibility_of_element_located((By.ID, 'modal'))) + self.assertTrue(modal.is_open) + self.assertIn("Add Person", modal.header) + + # Fill person form out and submit + person_name = "Test Person" + modal.name = person_name + modal.submit() + self.wait.until(EC.invisibility_of_element_located((By.ID, 'modal'))) + self.assertFalse(modal.is_open) + + # See new person selected + self.page.person_selector.toggle() + self.assertEqual(self.page.person_selector.options[0].name, person_name) + self.page.person_selector.toggle() + + # Change mind and add another + self.wait.until(animation_is_finished()) + modal = self.page.add_person() + self.wait.until(EC.visibility_of_element_located((By.ID, 'modal'))) + self.assertTrue(modal.is_open) + self.assertIn("Add Person", modal.header) + + person_name = "Test Person 2" + modal.name = person_name + modal.submit() + self.wait.until(EC.invisibility_of_element_located((By.ID, 'modal'))) + self.assertFalse(modal.is_open) + self.page.person_selector.toggle() + self.assertEqual(self.page.person_selector.options[0].name, person_name) + self.page.person_selector.toggle() + + # TODO + + def test_event_item_creation(self): + self.select_event_type("Rig") + + self.page.name = "Test Event with Items" + + self.page.person_selector.search(self.client.name) + self.page.person_selector.set_option(self.client.name, True) + # TODO This should not be necessary, normally closes automatically + self.page.person_selector.toggle() + self.assertFalse(self.page.person_selector.is_open) + + # Note to self, don't set dates before 2014, which is the beginning of VAT as far as the tests are concerned... + self.page.start_date = datetime.date(2084, 1, 1) + + modal = self.page.add_event_item() + self.wait.until(animation_is_finished()) + # See modal has opened + self.assertTrue(modal.is_open) + self.assertIn("New Event", modal.header) + + modal.name = "Test Item 1" + modal.description = "This is an item description\nthat for reasons unknown spans two lines" + modal.quantity = "2" + modal.price = "23.95" + modal.submit() + self.wait.until(animation_is_finished()) + + # Confirm item has been saved to json field + objectitems = self.driver.execute_script("return objectitems;") + self.assertEqual(1, len(objectitems)) + testitem = objectitems["-1"]['fields'] # as we are deliberately creating this we know the ID + self.assertEqual("Test Item 1", testitem['name']) + self.assertEqual("2", testitem['quantity']) # test a couple of "worse case" fields + + total = self.driver.find_element_by_id('total') + ActionChains(self.driver).move_to_element(total).perform() + + # See new item appear in table + row = self.page.item_row("-1") # ID number is known, see above + self.assertIn("Test Item 1", row.name) + self.assertIn("This is an item description", + row.description) + self.assertEqual('23.95', row.price) + self.assertEqual("2", row.quantity) + self.assertEqual('47.90', row.subtotal) + + # Check totals TODO convert to page properties + self.assertEqual("47.90", self.driver.find_element_by_id('sumtotal').text) + self.assertIn("(TBC)", self.driver.find_element_by_id('vat-rate').text) + self.assertEqual("9.58", self.driver.find_element_by_id('vat').text) + self.assertEqual("57.48", total.text) + + self.page.submit() + + # TODO Testing of internal rig (approval system interface) + + def test_non_rig_creation(self): + self.select_event_type("Non-Rig") + + self.assertFalse(self.page.person_selector.is_open) + + rig_name = "Test Non-Rig" + self.page.name = rig_name + + # Double-check we don't lose data when swapping + self.page.select_event_type("Rig") + self.wait.until(animation_is_finished()) + self.assertEquals(self.page.name, rig_name) + self.wait.until(animation_is_finished()) + self.page.select_event_type("Non-Rig") + + self.page.start_date = datetime.date(2020, 1, 1) + self.page.status = "Confirmed" + + self.page.submit() + self.assertTrue(self.page.success) + + +@screenshot_failure_cls +class TestEventDuplicate(BaseRigboardTest): + def setUp(self): + super().setUp() + self.testEvent = models.Event.objects.create(name="TE E1", status=models.Event.PROVISIONAL, + start_date=date.today() + timedelta(days=6), + description="start future no end", + purchase_order='TESTPO', + person=self.client, + auth_request_by=self.profile, + auth_request_at=base.create_datetime(2015, 0o6, 0o4, 10, 00), + auth_request_to="some@email.address") + + item1 = models.EventItem( + event=self.testEvent, + name="Test Item 1", + cost="10.00", + quantity="1", + order=1 + ).save() + item2 = models.EventItem( + event=self.testEvent, + name="Test Item 2", + description="Foo", + cost="9.72", + quantity="3", + order=2, + ).save() + self.page = pages.DuplicateEvent(self.driver, self.live_server_url, event_id=self.testEvent.pk).open() + + def test_rig_duplicate(self): + table = self.page.item_table + self.assertIn("Test Item 1", table.text) + self.assertIn("Test Item 2", table.text) + + # Check the info message is visible + self.assertIn("Event data duplicated but not yet saved", self.page.warning) + + modal = self.page.add_event_item() + self.wait.until(animation_is_finished()) + # See modal has opened + self.assertTrue(modal.is_open) + self.assertIn(self.testEvent.name, modal.header) + + modal.name = "Test Item 3" + modal.description = "This is an item description\nthat for reasons unknown spans two lines" + modal.quantity = "2" + modal.price = "23.95" + modal.submit() + self.wait.until(animation_is_finished()) + + # Attempt to save + self.page.submit() + + # TODO Rewrite when EventDetail page is implemented + newEvent = models.Event.objects.latest('pk') + + self.assertEqual(newEvent.auth_request_to, None) + self.assertEqual(newEvent.auth_request_by, None) + self.assertEqual(newEvent.auth_request_at, None) + + self.assertFalse(newEvent.authorised) + + self.assertNotIn("N%05d" % self.testEvent.pk, self.driver.find_element_by_xpath('//h1').text) + self.assertNotIn("Event data duplicated but not yet saved", self.page.warning) # Check info message not visible + + # Check the new items are visible + table = self.page.item_table + self.assertIn("Test Item 1", table.text) + self.assertIn("Test Item 2", table.text) + self.assertIn("Test Item 3", table.text) + + infoPanel = self.driver.find_element_by_xpath('//div[contains(text(), "Event Info")]/..') + self.assertIn("N%05d" % self.testEvent.pk, + infoPanel.find_element_by_xpath('//dt[text()="Based On"]/following-sibling::dd[1]').text) + # Check the PO hasn't carried through + self.assertNotIn("TESTPO", infoPanel.find_element_by_xpath('//dt[text()="PO"]/following-sibling::dd[1]').text) + + self.assertIn("N%05d" % self.testEvent.pk, + infoPanel.find_element_by_xpath('//dt[text()="Based On"]/following-sibling::dd[1]').text) + + self.driver.get(self.live_server_url + '/event/' + str(self.testEvent.pk)) # Go back to the old event + + # Check that based-on hasn't crept into the old event + infoPanel = self.driver.find_element_by_xpath('//div[contains(text(), "Event Info")]/..') + self.assertNotIn("N%05d" % self.testEvent.pk, + infoPanel.find_element_by_xpath('//dt[text()="Based On"]/following-sibling::dd[1]').text) + # Check the PO remains on the old event + self.assertIn("TESTPO", infoPanel.find_element_by_xpath('//dt[text()="PO"]/following-sibling::dd[1]').text) + + self.assertNotIn("N%05d" % self.testEvent.pk, + infoPanel.find_element_by_xpath('//dt[text()="Based On"]/following-sibling::dd[1]').text) + + # Check the items are as they were + table = self.page.item_table # ID number is known, see above + self.assertIn("Test Item 1", table.text) + self.assertIn("Test Item 2", table.text) + self.assertNotIn("Test Item 3", table.text) + + +@screenshot_failure_cls +class TestEventEdit(BaseRigboardTest): + def setUp(self): + super().setUp() + self.testEvent = models.Event.objects.create(name="TE E1", status=models.Event.PROVISIONAL, + start_date=date.today() + timedelta(days=6), + description="start future no end", + purchase_order='TESTPO', + person=self.client, + auth_request_by=self.profile, + auth_request_at=base.create_datetime(2015, 0o6, 0o4, 10, 00), + auth_request_to="some@email.address") + + item1 = models.EventItem( + event=self.testEvent, + name="Test Item 1", + cost="10.00", + quantity="1", + order=1 + ).save() + item2 = models.EventItem( + event=self.testEvent, + name="Test Item 2", + description="Foo", + cost="9.72", + quantity="3", + order=2, + ).save() + self.page = pages.EditEvent(self.driver, self.live_server_url, event_id=self.testEvent.pk).open() + + def test_rig_edit(self): + self.page.name = "Edited Event" + + modal = self.page.add_event_item() + self.wait.until(animation_is_finished()) + # See modal has opened + self.assertTrue(modal.is_open) + self.assertIn(self.testEvent.name, modal.header) + + modal.name = "Test Item 3" + modal.description = "This is an item description\nthat for reasons unknown spans two lines" + modal.quantity = "2" + modal.price = "23.95" + modal.submit() + self.wait.until(animation_is_finished()) + + # Attempt to save + ActionChains(self.driver).move_to_element(self.page.item_table).perform() + self.page.submit() + + self.assertTrue(self.page.success) + + self.page = pages.EventDetail(self.driver, self.live_server_url, event_id=self.testEvent.pk).open() + self.testEvent.refresh_from_db() + self.assertIn(self.testEvent.name, self.page.event_name) + self.assertEqual(self.page.name, self.testEvent.person.name) + # Check the new items are visible + table = self.page.item_table + self.assertIn("Test Item 3", table.text) + + +@screenshot_failure_cls +class TestEventDetail(BaseRigboardTest): + def setUp(self): + super().setUp() + self.testEvent = models.Event.objects.create(name="TE E1", status=models.Event.PROVISIONAL, + start_date=date.today() + timedelta(days=6), + description="start future no end", + purchase_order='TESTPO', + person=self.client, + auth_request_by=self.profile, + auth_request_at=base.create_datetime(2015, 0o6, 0o4, 10, 00), + auth_request_to="some@email.address") + + item1 = models.EventItem( + event=self.testEvent, + name="Test Item 1", + cost="10.00", + quantity="1", + order=1 + ).save() + item2 = models.EventItem( + event=self.testEvent, + name="Test Item 2", + description="Foo", + cost="9.72", + quantity="3", + order=2, + ).save() + self.page = pages.EventDetail(self.driver, self.live_server_url, event_id=self.testEvent.pk).open() + + def test_rig_detail(self): + self.assertIn("N%05d | %s" % (self.testEvent.pk, self.testEvent.name), self.page.event_name) + self.assertEqual(self.client.name, self.page.name) + self.assertEqual(self.client.email, self.page.email) + self.assertEqual(self.client.phone, None) + + +@screenshot_failure_cls +class TestCalendar(BaseRigboardTest): + def setUp(self): + super().setUp() + self.all_events = set(range(1, 18)) + self.current_events = (1, 2, 3, 6, 7, 8, 10, 11, 12, 14, 15, 16, 18) + self.not_current_events = set(self.all_events) - set(self.current_events) + + # produce 7 normal events - 5 current - 1 last week - 1 two years ago - 2 provisional - 2 confirmed - 3 booked + models.Event.objects.create(name="TE E1", status=models.Event.PROVISIONAL, + start_date=date.today() + timedelta(days=6), description="start future no end") + models.Event.objects.create(name="TE E2", status=models.Event.PROVISIONAL, start_date=date.today(), + description="start today no end") + models.Event.objects.create(name="TE E3", status=models.Event.CONFIRMED, start_date=date.today(), + end_date=date.today(), description="start today with end today") + models.Event.objects.create(name="TE E4", status=models.Event.CONFIRMED, + start_date=date.today() - timedelta(weeks=104), + description="start past 2 years no end") + models.Event.objects.create(name="TE E5", status=models.Event.BOOKED, + start_date=date.today() - timedelta(days=7), + end_date=date.today() - timedelta(days=1), + description="start past 1 week with end past") + models.Event.objects.create(name="TE E6", status=models.Event.BOOKED, + start_date=date.today() - timedelta(days=2), + start_time=time(8, 00), + end_date=date.today() + timedelta(days=2), + end_time=time(23, 00), description="start past, end future") + models.Event.objects.create(name="TE E7", status=models.Event.BOOKED, + start_date=date.today() + timedelta(days=2), + end_date=date.today() + timedelta(days=2), description="start + end in future") + + # 2 cancelled - 1 current + models.Event.objects.create(name="TE E8", start_date=date.today() + timedelta(days=2), + end_date=date.today() + timedelta(days=2), status=models.Event.CANCELLED, + description="cancelled in future") + models.Event.objects.create(name="TE E9", start_date=date.today() - timedelta(days=1), + end_date=date.today() + timedelta(days=2), status=models.Event.CANCELLED, + description="cancelled and started") + + # 5 dry hire - 3 current - 1 cancelled + models.Event.objects.create(name="TE E10", start_date=date.today(), dry_hire=True, description="dryhire today") + models.Event.objects.create(name="TE E11", start_date=date.today(), dry_hire=True, checked_in_by=self.profile, + description="dryhire today, checked in") + models.Event.objects.create(name="TE E12", start_date=date.today() - timedelta(days=1), dry_hire=True, + status=models.Event.BOOKED, description="dryhire past") + models.Event.objects.create(name="TE E13", start_date=date.today() - timedelta(days=2), dry_hire=True, + checked_in_by=self.profile, description="dryhire past checked in") + models.Event.objects.create(name="TE E14", start_date=date.today(), dry_hire=True, + status=models.Event.CANCELLED, description="dryhire today cancelled") + + # 4 non rig - 3 current + models.Event.objects.create(name="TE E15", start_date=date.today(), is_rig=False, description="non rig today") + models.Event.objects.create(name="TE E16", start_date=date.today() + timedelta(days=1), is_rig=False, + description="non rig tomorrow") + models.Event.objects.create(name="TE E17", start_date=date.today() - timedelta(days=1), is_rig=False, + description="non rig yesterday") + models.Event.objects.create(name="TE E18", start_date=date.today(), is_rig=False, status=models.Event.CANCELLED, + description="non rig today cancelled") + + self.page = pages.UserPage(self.driver, self.live_server_url).open() + + def test_api_key_generation(self): + # Completes and comes back to /user/ + # Checks that no api key is displayed + self.assertEqual("No API Key Generated", self.page.api_key) + + # Now creates an API key, and check a URL is displayed one + self.page.generate_key() + self.assertIn("rigs.ics", self.page.cal_url) + self.assertNotIn("?", self.page.cal_url) + + # Lets change everything so it's not the default value + self.page.toggle_filter('rig') + self.page.toggle_filter('non-rig') + self.page.toggle_filter('dry-hire') + self.page.toggle_filter('cancelled') + self.page.toggle_filter('provisional') + self.page.toggle_filter('confirmed') + + # and then check the url is correct + self.assertIn( + "rigs.ics?rig=false&non-rig=false&dry-hire=false&cancelled=true&provisional=false&confirmed=false", + self.page.cal_url) + + # Awesome - all seems to work + + def test_ics_files(self): + specialEvent = models.Event.objects.get(name="TE E6") + + # Now creates an API key, and check a URL is displayed one + self.page.generate_key() + + c = Client() + + # Default settings - should have all non-cancelled events + # Get the ical file (can't do this in selanium because reasons) + icalUrl = self.page.cal_url + response = c.get(self.page.cal_url) + self.assertEqual(200, response.status_code) + + # content = response.content.decode('utf-8') + + # Check has entire file + self.assertContains(response, "BEGIN:VCALENDAR") + self.assertContains(response, "END:VCALENDAR") + + expectedIn = [1, 2, 3, 5, 6, 7, 10, 11, 12, 13, 15, 16, 17] + for test in range(1, 18): + if test in expectedIn: + self.assertContains(response, "TE E" + str(test) + " ") + else: + self.assertNotContains(response, "TE E" + str(test) + " ") + + # Check that times have been included correctly + self.assertContains(response, + specialEvent.start_date.strftime('%Y%m%d') + 'T' + specialEvent.start_time.strftime( + '%H%M%S')) + self.assertContains(response, + specialEvent.end_date.strftime('%Y%m%d') + 'T' + specialEvent.end_time.strftime('%H%M%S')) + + # Only non rigs + self.page.toggle_filter('rig') + self.page.toggle_filter('non-rig') + + icalUrl = self.page.cal_url + response = c.get(icalUrl) + self.assertEqual(200, response.status_code) + + expectedIn = [10, 11, 12, 13] + for test in range(1, 18): + if test in expectedIn: + self.assertContains(response, "TE E" + str(test) + " ") + else: + self.assertNotContains(response, "TE E" + str(test) + " ") + + # Only provisional rigs + self.page.toggle_filter('rig') + self.page.toggle_filter('dry-hire') + self.page.toggle_filter('confirmed') + + icalUrl = self.page.cal_url + response = c.get(icalUrl) + self.assertEqual(200, response.status_code) + + expectedIn = [1, 2] + for test in range(1, 18): + if test in expectedIn: + self.assertContains(response, "TE E" + str(test) + " ") + else: + self.assertNotContains(response, "TE E" + str(test) + " ") + + # Only cancelled non-rigs + self.page.toggle_filter('rig') + self.page.toggle_filter('non-rig') + self.page.toggle_filter('provisional') + self.page.toggle_filter('cancelled') + + icalUrl = self.page.cal_url + response = c.get(icalUrl) + self.assertEqual(200, response.status_code) + + expectedIn = [18] + for test in range(1, 18): + if test in expectedIn: + self.assertContains(response, "TE E" + str(test) + " ") + else: + self.assertNotContains(response, "TE E" + str(test) + " ") + + # Nothing selected + self.page.toggle_filter('non-rig') + self.page.toggle_filter('cancelled') + + icalUrl = self.page.cal_url + response = c.get(icalUrl) + self.assertEqual(200, response.status_code) + + expectedIn = [] + for test in range(1, 18): + if test in expectedIn: + self.assertContains(response, "TE E" + str(test) + " ") + else: + self.assertNotContains(response, "TE E" + str(test) + " ") + + # Wow - that was a lot of tests + + +@screenshot_failure_cls +class TestHealthAndSafety(BaseRigboardTest): + def setUp(self): + super().setUp() + self.profile = models.Profile.objects.get_or_create( + first_name='Test', + last_name='TEC User', + username='eventtest', + email='teccie@functional.test', + is_superuser=True # lazily grant all permissions + )[0] + self.testEvent = models.Event.objects.create(name="TE E1", status=models.Event.PROVISIONAL, + start_date=date.today() + timedelta(days=6), + description="start future no end", + purchase_order='TESTPO', + person=self.client) + self.page = pages.EventDetail(self.driver, self.live_server_url, event_id=self.testEvent.pk).open() + + # TODO Can I loop through all the boolean fields and test them at once? + def test_ra_creation(self): + self.page = pages.CreateRiskAssessment(self.driver, self.live_server_url, event_id=self.testEvent.pk).open() + + # Check there are no defaults + self.assertIsNone(self.page.nonstandard_equipment) + + # No database side validation, only HTML5. + + self.page.nonstandard_equipment = False + self.page.nonstandard_use = False + self.page.contractors = False + self.page.other_companies = False + self.page.crew_fatigue = False + self.page.general_notes = "There are no notes." + self.page.big_power = False + self.page.power_mic.search(self.profile.name) + self.page.power_mic.set_option(self.profile.name, True) + # TODO This should not be necessary, normally closes automatically + self.page.power_mic.toggle() + self.assertFalse(self.page.power_mic.is_open) + self.page.generators = False + self.page.other_companies_power = False + self.page.nonstandard_equipment_power = False + self.page.multiple_electrical_environments = False + self.page.power_notes = "Remember to bring some power" + self.page.noise_monitoring = False + self.page.sound_notes = "Loud, but not too loud" + self.page.known_venue = True + self.page.safe_loading = True + self.page.safe_storage = True + self.page.area_outside_of_control = False + self.page.barrier_required = False + self.page.nonstandard_emergency_procedure = False + self.page.special_structures = False + self.page.persons_responsible_structures = "Nobody and her cat, She" + self.page.suspended_structures = False + + self.page.submit() + self.assertTrue(self.page.success) + + # Test that we can't make another one + self.page = pages.CreateRiskAssessment(self.driver, self.live_server_url, event_id=self.testEvent.pk).open() + self.assertIn('edit', self.driver.current_url) + + def test_ra_edit(self): + # Create assessment to edit + self.page = pages.CreateRiskAssessment(self.driver, self.live_server_url, event_id=self.testEvent.pk).open() + self.page.nonstandard_equipment = False + self.page.nonstandard_use = False + self.page.contractors = False + self.page.other_companies = False + self.page.crew_fatigue = False + self.page.general_notes = "There are no notes." + self.page.big_power = False + self.page.power_mic.search(self.profile.name) + self.page.power_mic.toggle() + self.assertFalse(self.page.power_mic.is_open) + self.page.remove_all_required() + self.page.submit() + self.page = pages.EditRiskAssessment(self.driver, self.live_server_url, pk=models.RiskAssessment.objects.get(event=self.testEvent.pk).pk).open() + self.page.nonstandard_equipment = nse = True + self.page.general_notes = gn = "There are some notes, but I've not written them here as that would be helpful" + self.page.submit() + self.assertTrue(self.page.success) + # Check that data is right + ra = models.RiskAssessment.objects.get(event=self.testEvent.pk) + self.assertEqual(ra.general_notes, gn) + self.assertEqual(ra.nonstandard_equipment, nse) + + def test_ec_create_small(self): + self.page = pages.CreateEventChecklist(self.driver, self.live_server_url, event_id=self.testEvent.pk).open() + + self.page.safe_parking = True + self.page.safe_packing = True + self.page.exits = True + self.page.trip_hazard = True + self.page.warning_signs = True + self.page.ear_plugs = True + self.page.hs_location = "The Moon" + self.page.extinguishers_location = "With the rest of the fire" + # If we do this first the search fails, for ... reasons + self.page.power_mic.search(self.profile.name) + self.page.power_mic.toggle() + self.assertFalse(self.page.power_mic.is_open) + + self.page.select_size('Small') + self.wait.until(animation_is_finished()) + self.assertFalse(self.driver.find_element(By.XPATH, '(//*[@id="id_earthing"])[2]').is_displayed()) + self.assertTrue(self.driver.find_element(By.XPATH, '(//*[@id="id_earthing"])[1]').is_displayed()) + self.page.earthing = True + self.page.rcds = True + self.page.supply_test = True + self.page.pat = True + + self.page.submit() + self.assertTrue(self.page.success) + + def test_ec_create_medium(self): + self.page = pages.CreateEventChecklist(self.driver, self.live_server_url, event_id=self.testEvent.pk).open() + + self.page.safe_parking = True + self.page.safe_packing = True + self.page.exits = True + self.page.trip_hazard = True + self.page.warning_signs = True + self.page.ear_plugs = True + self.page.hs_location = "Death Valley" + self.page.extinguishers_location = "With the rest of the fire" + # If we do this first the search fails, for ... reasons + self.page.power_mic.search(self.profile.name) + self.page.power_mic.toggle() + self.assertFalse(self.page.power_mic.is_open) + + self.page.select_size('Medium') + self.wait.until(animation_is_finished()) + self.assertFalse(self.driver.find_element(By.XPATH, '(//*[@id="id_earthing"])[1]').is_displayed()) + self.assertTrue(self.driver.find_element(By.XPATH, '(//*[@id="id_earthing"])[2]').is_displayed()) + self.page.earthing_m = True + self.page.pat_m = True + self.page.source_rcd = True + self.page.labelling = True + self.page.fd_voltage_l1 = 240 + self.page.fd_voltage_l2 = 235 + self.page.fd_voltage_l3 = 0 + self.page.fd_phase_rotation = True + self.page.fd_earth_fault = 666 + self.page.fd_pssc = 1984 + self.page.w1_description = "In the carpark, by the bins" + self.page.w1_polarity = True + self.page.w1_voltage = 240 + self.page.w1_earth_fault = 333 + + # Gotta scroll to make the button clickable + self.driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") + self.page.submit() + self.assertTrue(self.page.success) + + def test_ec_create_extras(self): + self.page = pages.CreateEventChecklist(self.driver, self.live_server_url, event_id=self.testEvent.pk).open() + self.page.add_vehicle() + self.page.add_crew() + + self.page.safe_parking = True + self.page.safe_packing = True + self.page.exits = True + self.page.trip_hazard = True + self.page.warning_signs = True + self.page.ear_plugs = True + self.page.hs_location = "The Moon" + self.page.extinguishers_location = "With the rest of the fire" + # If we do this first the search fails, for ... reasons + self.page.power_mic.search(self.profile.name) + self.page.power_mic.toggle() + self.assertFalse(self.page.power_mic.is_open) + + vehicle_name = 'Brian' + self.driver.find_element(By.XPATH, '//*[@name="vehicle_-1"]').send_keys(vehicle_name) + driver = base_regions.BootstrapSelectElement(self.page, self.driver.find_element(By.XPATH, '(//*[contains(@class,"bootstrap-select")])[2]')) + driver.search(self.profile.name) + driver.toggle() + + crew = self.profile + role = "MIC" + crew_select = base_regions.BootstrapSelectElement(self.page, self.driver.find_element(By.XPATH, '(//*[contains(@class,"bootstrap-select")])[3]')) + start_time = base_regions.DateTimePicker(self.page, self.driver.find_element(By.XPATH, '//*[@name="start_-1"]')) + end_time = base_regions.DateTimePicker(self.page, self.driver.find_element(By.XPATH, '//*[@name="end_-1"]')) + + start_time.set_value(timezone.make_aware(datetime.datetime(2015, 1, 1, 9, 0))) + # TODO Validation of end before start + end_time.set_value(timezone.make_aware(datetime.datetime(2015, 1, 1, 10, 30))) + crew_select.search(crew.name) + crew_select.toggle() + self.driver.find_element(By.XPATH, '//*[@name="role_-1"]').send_keys(role) + + self.page.select_size('Small') + self.wait.until(animation_is_finished()) + self.assertFalse(self.driver.find_element(By.XPATH, '(//*[@id="id_earthing"])[2]').is_displayed()) + self.assertTrue(self.driver.find_element(By.XPATH, '(//*[@id="id_earthing"])[1]').is_displayed()) + self.page.earthing = True + self.page.rcds = True + self.page.supply_test = True + self.page.pat = True + + self.page.submit() + self.assertTrue(self.page.success) + + checklist = models.EventChecklist.objects.get(event=self.testEvent.pk) + vehicle = models.EventChecklistVehicle.objects.get(checklist=checklist.pk) + self.assertEqual(vehicle_name, vehicle.vehicle) + crew_obj = models.EventChecklistCrew.objects.get(checklist=checklist.pk) + self.assertEqual(crew.pk, crew_obj.crewmember.pk) + self.assertEqual(role, crew_obj.role) diff --git a/RIGS/tests/test_unit.py b/RIGS/tests/test_unit.py index 5204aaa1..beaa83e1 100644 --- a/RIGS/tests/test_unit.py +++ b/RIGS/tests/test_unit.py @@ -509,7 +509,7 @@ class TestHSLogic(TestCase): extinguishers_location="Somewhere, I forgot", earthing=False, pat=False, - medium_event=False + event_size=0 ), } @@ -551,10 +551,3 @@ class TestHSLogic(TestCase): response = self.client.get(request_url, follow=True) self.assertRedirects(response, expected_url, status_code=302, target_status_code=200) - - def test_checklist_redirect(self): - request_url = reverse('event_ec', kwargs={'pk': self.events[1].pk}) - expected_url = reverse('ec_edit', kwargs={'pk': self.checklists[1].pk}) - - response = self.client.get(request_url, follow=True) - self.assertRedirects(response, expected_url, status_code=302, target_status_code=200)