Pages/start of tests for EventChecklists

This commit is contained in:
2020-09-14 16:26:02 +01:00
parent aa0184a5dc
commit 6426880708
6 changed files with 134 additions and 48 deletions

View File

@@ -6,6 +6,7 @@ from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support.select import Select from selenium.webdriver.support.select import Select
from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import NoSuchElementException
import datetime import datetime
@@ -138,7 +139,7 @@ class RadioSelect(Region): # Currently only works for yes/no radio selects
def value(self): def value(self):
try: try:
return parse_bool_from_string(self.find_element(By.CSS_SELECTOR, '.custom-control-input:checked').get_attribute("value").lower()) return parse_bool_from_string(self.find_element(By.CSS_SELECTOR, '.custom-control-input:checked').get_attribute("value").lower())
except: except NoSuchElementException:
return None return None

View File

@@ -728,6 +728,10 @@ class EventChecklist(models.Model, RevisionMixin):
def clean(self): def clean(self):
errdict = {} errdict = {}
if self.power_mic is None:
errdict["power_mic"] = ["You must select a Power MIC"]
if self.earthing is None or self.pat is None: if self.earthing is None or self.pat is None:
errdict['earthing'] = 'Fill out the electrical checks' errdict['earthing'] = 'Fill out the electrical checks'

View File

@@ -20,9 +20,11 @@
<tr> <tr>
<th scope="col">Event</th> <th scope="col">Event</th>
{# mmm hax #} {# mmm hax #}
{% if object_list.0 != None %}
{% for field in fields %} {% for field in fields %}
<th scope="col">{{ object_list.0|verbose_name:field|title }}</th> <th scope="col">{{ object_list.0|verbose_name:field|title }}</th>
{% endfor %} {% endfor %}
{% endif %}
<th scope="col"></th> <th scope="col"></th>
</tr> </tr>
</thead> </thead>

View File

@@ -162,6 +162,24 @@ class CreateEvent(FormPage):
return '/create' not in self.driver.current_url return '/create' not in self.driver.current_url
class DuplicateEvent(CreateEvent):
URL_TEMPLATE = 'event/{event_id}/duplicate'
_submit_locator = (By.XPATH, '/html/body/div[1]/form/div/div[5]/div/button')
@property
def success(self):
return '/duplicate' not in self.driver.current_url
class EditEvent(CreateEvent):
URL_TEMPLATE = 'event/{event_id}/edit'
_submit_locator = (By.XPATH, '/html/body/div[1]/form/div/div[5]/div/button')
@property
def success(self):
return '/edit' not in self.driver.current_url
class CreateRiskAssessment(FormPage): class CreateRiskAssessment(FormPage):
URL_TEMPLATE = 'event/{event_id}/ra/' URL_TEMPLATE = 'event/{event_id}/ra/'
@@ -176,7 +194,6 @@ class CreateRiskAssessment(FormPage):
'crew_fatigue': (regions.RadioSelect, (By.ID, 'id_crew_fatigue')), 'crew_fatigue': (regions.RadioSelect, (By.ID, 'id_crew_fatigue')),
'general_notes': (regions.TextBox, (By.ID, 'id_general_notes')), 'general_notes': (regions.TextBox, (By.ID, 'id_general_notes')),
'big_power': (regions.RadioSelect, (By.ID, 'id_big_power')), 'big_power': (regions.RadioSelect, (By.ID, 'id_big_power')),
#'power_mic': (regions.RadioSelect, (By.ID, 'id_power_mic')),
'generators': (regions.RadioSelect, (By.ID, 'id_generators')), 'generators': (regions.RadioSelect, (By.ID, 'id_generators')),
'other_companies_power': (regions.RadioSelect, (By.ID, 'id_other_companies_power')), 'other_companies_power': (regions.RadioSelect, (By.ID, 'id_other_companies_power')),
'nonstandard_equipment_power': (regions.RadioSelect, (By.ID, 'id_nonstandard_equipment_power')), 'nonstandard_equipment_power': (regions.RadioSelect, (By.ID, 'id_nonstandard_equipment_power')),
@@ -203,24 +220,50 @@ class CreateRiskAssessment(FormPage):
def success(self): def success(self):
return '/event/ra' in self.driver.current_url return '/event/ra' in self.driver.current_url
class DuplicateEvent(CreateEvent):
URL_TEMPLATE = 'event/{event_id}/duplicate'
_submit_locator = (By.XPATH, '/html/body/div[1]/form/div/div[5]/div/button')
@property class EditRiskAssessment(CreateRiskAssessment):
def success(self): URL_TEMPLATE = 'event/ra/{pk}/edit'
return '/duplicate' not in self.driver.current_url
class EditEvent(CreateEvent):
URL_TEMPLATE = 'event/{event_id}/edit'
_submit_locator = (By.XPATH, '/html/body/div[1]/form/div/div[5]/div/button')
@property @property
def success(self): def success(self):
return '/edit' not in self.driver.current_url return '/edit' not in self.driver.current_url
class CreateEventChecklist(FormPage):
URL_TEMPLATE = 'event/{event_id}/checklist'
_submit_locator = (By.XPATH, "//button[@type='submit' and contains(., 'Save')]")
_power_mic_selector = (By.CSS_SELECTOR, ".bootstrap-select")
_add_vehicle_locator = (By.XPATH, "//button[contains(., 'Vehicle')]")
_add_crew_locator = (By.XPATH, "//button[contains(., 'Crew')]")
form_items = {
'safe_parking': (regions.CheckBox, (By.ID, 'id_safe_parking')),
'safe_packing': (regions.CheckBox, (By.ID, 'id_safe_packing')),
'exits': (regions.CheckBox, (By.ID, 'id_exits')),
'trip_hazard': (regions.CheckBox, (By.ID, 'id_trip_hazard')),
'warning_signs': (regions.CheckBox, (By.ID, 'id_warning_signs')),
'ear_plugs': (regions.CheckBox, (By.ID, 'id_ear_plugs')),
'hs_location': (regions.TextBox, (By.ID, 'id_hs_location')),
'extinguishers_location': (regions.TextBox, (By.ID, 'id_extinguishers_location')),
'rcds': (regions.CheckBox, (By.ID, 'id_rcds')),
'supply_test': (regions.CheckBox, (By.ID, 'id_supply_test')),
'earthing': (regions.CheckBox, (By.ID, 'id_earthing')),
'pat': (regions.CheckBox, (By.ID, 'id_pat')),
}
def select_size(self, size):
self.find_element(By.XPATH, '//button[.="{}"]'.format(size)).click()
@property
def power_mic(self):
return regions.BootstrapSelectElement(self, self.find_element(*self._power_mic_selector))
@property
def success(self):
return '{event_id}' not in self.driver.current_url
class GenericList(BasePage): class GenericList(BasePage):
_search_selector = (By.CSS_SELECTOR, 'div.input-group:nth-child(2) > input:nth-child(1)') _search_selector = (By.CSS_SELECTOR, 'div.input-group:nth-child(2) > input:nth-child(1)')
_search_go_selector = (By.ID, 'id_search') _search_go_selector = (By.ID, 'id_search')

View File

@@ -868,7 +868,6 @@ class TECEventAuthorisationTest(TestCase):
self.assertIsNotNone(self.event.auth_request_at) self.assertIsNotNone(self.event.auth_request_at)
@screenshot_failure_cls @screenshot_failure_cls
class TestHealthAndSafety(BaseRigboardTest): class TestHealthAndSafety(BaseRigboardTest):
def setUp(self): def setUp(self):
@@ -876,7 +875,7 @@ class TestHealthAndSafety(BaseRigboardTest):
self.profile = models.Profile.objects.get_or_create( self.profile = models.Profile.objects.get_or_create(
first_name='Test', first_name='Test',
last_name='TEC User', last_name='TEC User',
username='eventauthtest', username='eventtest',
email='teccie@functional.test', email='teccie@functional.test',
is_superuser=True # lazily grant all permissions is_superuser=True # lazily grant all permissions
)[0] )[0]
@@ -884,28 +883,10 @@ class TestHealthAndSafety(BaseRigboardTest):
start_date=date.today() + timedelta(days=6), start_date=date.today() + timedelta(days=6),
description="start future no end", description="start future no end",
purchase_order='TESTPO', purchase_order='TESTPO',
person=self.client, 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() 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): def test_ra_creation(self):
self.page = pages.CreateRiskAssessment(self.driver, self.live_server_url, event_id=self.testEvent.pk).open() self.page = pages.CreateRiskAssessment(self.driver, self.live_server_url, event_id=self.testEvent.pk).open()
@@ -945,3 +926,58 @@ class TestHealthAndSafety(BaseRigboardTest):
self.page.submit() self.page.submit()
self.assertTrue(self.page.success) 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.page.earthing = True
self.page.rcds = True
self.page.supply_test = True
self.page.pat = True
self.page.submit()
self.assertTrue(self.page.success)

View File

@@ -71,25 +71,25 @@ urlpatterns = [
name='event_duplicate'), name='event_duplicate'),
# Event H&S # Event H&S
path('event/hs/', permission_required_with_403('RIGS.change_event')(hs.HSList.as_view()), name='hs_list'), path('event/hs/', permission_required_with_403('RIGS.view_riskassessment')(hs.HSList.as_view()), name='hs_list'),
path('event/<int:pk>/ra/', permission_required_with_403('RIGS.change_event')(hs.EventRiskAssessmentCreate.as_view()), path('event/<int:pk>/ra/', permission_required_with_403('RIGS.add_riskassessment')(hs.EventRiskAssessmentCreate.as_view()),
name='event_ra'), name='event_ra'),
path('event/ra/<int:pk>/', permission_required_with_403('RIGS.change_event')(hs.EventRiskAssessmentDetail.as_view()), path('event/ra/<int:pk>/', permission_required_with_403('RIGS.view_riskassessment')(hs.EventRiskAssessmentDetail.as_view()),
name='ra_detail'), name='ra_detail'),
path('event/ra/<int:pk>/edit/', permission_required_with_403('RIGS.change_event')(hs.EventRiskAssessmentEdit.as_view()), path('event/ra/<int:pk>/edit/', permission_required_with_403('RIGS.change_riskassessment')(hs.EventRiskAssessmentEdit.as_view()),
name='ra_edit'), name='ra_edit'),
path('event/ra/list', permission_required_with_403('RIGS.change_event')(hs.EventRiskAssessmentList.as_view()), path('event/ra/list', permission_required_with_403('RIGS.view_riskassessment')(hs.EventRiskAssessmentList.as_view()),
name='ra_list'), name='ra_list'),
path('event/ra/<int:pk>/review/', permission_required_with_403('RIGS.review_riskassessment')(hs.EventRiskAssessmentReview.as_view()), name='ra_review'), path('event/ra/<int:pk>/review/', permission_required_with_403('RIGS.review_riskassessment')(hs.EventRiskAssessmentReview.as_view()), name='ra_review'),
path('event/<int:pk>/checklist/', permission_required_with_403('RIGS.change_event')(hs.EventChecklistCreate.as_view()), path('event/<int:pk>/checklist/', permission_required_with_403('RIGS.add_eventchecklist')(hs.EventChecklistCreate.as_view()),
name='event_ec'), name='event_ec'),
path('event/checklist/<int:pk>/', permission_required_with_403('RIGS.change_event')(hs.EventChecklistDetail.as_view()), path('event/checklist/<int:pk>/', permission_required_with_403('RIGS.view_eventchecklist')(hs.EventChecklistDetail.as_view()),
name='ec_detail'), name='ec_detail'),
path('event/checklist/<int:pk>/edit/', permission_required_with_403('RIGS.change_event')(hs.EventChecklistEdit.as_view()), path('event/checklist/<int:pk>/edit/', permission_required_with_403('RIGS.change_eventchecklist')(hs.EventChecklistEdit.as_view()),
name='ec_edit'), name='ec_edit'),
path('event/checklist/list', permission_required_with_403('RIGS.change_event')(hs.EventChecklistList.as_view()), path('event/checklist/list', permission_required_with_403('RIGS.view_eventchecklist')(hs.EventChecklistList.as_view()),
name='ec_list'), name='ec_list'),
path('event/checklist/<int:pk>/review/', permission_required_with_403('RIGS.review_eventchecklist')(hs.EventChecklistReview.as_view()), name='ec_review'), path('event/checklist/<int:pk>/review/', permission_required_with_403('RIGS.review_eventchecklist')(hs.EventChecklistReview.as_view()), name='ec_review'),