Start tests for audit

This commit is contained in:
2020-02-23 23:31:12 +00:00
parent e5a1830b00
commit da0c9ba87b
3 changed files with 159 additions and 3 deletions

View File

@@ -142,7 +142,7 @@
</div> </div>
{% if not request.is_ajax %} {% if not request.is_ajax %}
<div class="form-group pull-right"> <div class="form-group pull-right">
<button class="btn btn-success" type="submit" form="asset_audit_form">Mark Audited</button> <button class="btn btn-success" type="submit" form="asset_audit_form" id="id_mark_audited">Mark Audited</button>
</div> </div>
{% endif %} {% endif %}
</form> </form>
@@ -150,6 +150,6 @@
{% block footer %} {% block footer %}
<div class="form-group"> <div class="form-group">
<button class="btn btn-success pull-right" type="submit" form="asset_audit_form" onclick="onAuditClick({{form.asset_id.value}});">Mark Audited</button> <button class="btn btn-success pull-right" type="submit" form="asset_audit_form" onclick="onAuditClick({{form.asset_id.value}});" id="id_mark_audited">Mark Audited</button>
</div> </div>
{% endblock %} {% endblock %}

View File

@@ -6,7 +6,7 @@ from selenium.webdriver import Chrome
from django.urls import reverse from django.urls import reverse
from PyRIGS.tests import regions from PyRIGS.tests import regions
from PyRIGS.tests.pages import BasePage, FormPage from PyRIGS.tests.pages import BasePage, FormPage
import pdb from selenium.common.exceptions import NoSuchElementException
class AssetList(BasePage): class AssetList(BasePage):
@@ -186,3 +186,109 @@ class SupplierEdit(SupplierForm):
@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 AssetAuditList(AssetList):
URL_TEMPLATE = reverse('asset_audit_list')
_search_text_locator = (By.ID, 'id_query')
_go_button_locator = (By.ID, 'searchButton')
_modal_locator = (By.ID, 'modal')
@property
def modal(self):
return self.AssetAuditModal(self, self.find_element(*self._modal_locator))
@property
def query(self):
return self.find_element(*self._search_text_locator).text
def set_query(self, queryString):
element = self.find_element(*self._search_text_locator)
element.clear()
element.send_keys(queryString)
def search(self):
self.find_element(*self._go_button_locator).click()
class AssetAuditModal(Region):
_errors_selector = (By.CLASS_NAME, "alert-danger")
# Don't use the usual success selector - that tries and fails to hit the '10m long cable' helper button...
_submit_locator = (By.ID, "id_mark_audited")
form_items = {
'asset_id': (regions.TextBox, (By.ID, 'id_asset_id')),
'description': (regions.TextBox, (By.ID, 'id_description')),
'is_cable': (regions.CheckBox, (By.ID, 'id_is_cable')),
'serial_number': (regions.TextBox, (By.ID, 'id_serial_number')),
'salvage_value': (regions.TextBox, (By.ID, 'id_salvage_value')),
'date_acquired': (regions.DatePicker, (By.ID, 'id_date_acquired')),
'category': (regions.SingleSelectPicker, (By.ID, 'id_category')),
'status': (regions.SingleSelectPicker, (By.ID, 'id_status')),
'plug': (regions.SingleSelectPicker, (By.ID, 'id_plug')),
'socket': (regions.SingleSelectPicker, (By.ID, 'id_socket')),
'length': (regions.TextBox, (By.ID, 'id_length')),
'csa': (regions.TextBox, (By.ID, 'id_csa')),
'circuits': (regions.TextBox, (By.ID, 'id_circuits')),
'cores': (regions.TextBox, (By.ID, 'id_cores'))
}
@property
def is_displayed(self):
return self.root.is_displayed()
@property
def errors(self):
try:
error_page = self.ErrorPage(self, self.find_element(*self._errors_selector))
return error_page.errors
except NoSuchElementException:
return None
def submit(self):
previous_errors = self.errors
self.root.find_element(*self._submit_locator).click()
# self.wait.until(lambda x: not self.is_displayed)
class ErrorPage(Region):
_error_item_selector = (By.CSS_SELECTOR, "dl>span")
class ErrorItem(Region):
_field_selector = (By.CSS_SELECTOR, "dt")
_error_selector = (By.CSS_SELECTOR, "dd>ul>li")
@property
def field_name(self):
return self.find_element(*self._field_selector).text
@property
def errors(self):
return [x.text for x in self.find_elements(*self._error_selector)]
@property
def errors(self):
error_items = [self.ErrorItem(self, x) for x in self.find_elements(*self._error_item_selector)]
errors = {}
for error in error_items:
errors[error.field_name] = error.errors
return errors
def remove_all_required(self):
self.driver.execute_script("Array.from(document.getElementsByTagName(\"input\")).forEach(function (el, ind, arr) { el.removeAttribute(\"required\")});")
self.driver.execute_script("Array.from(document.getElementsByTagName(\"select\")).forEach(function (el, ind, arr) { el.removeAttribute(\"required\")});")
def __getattr__(self, name):
if name in self.form_items:
element = self.form_items[name]
form_element = element[0](self, self.find_element(*element[1]))
return form_element.value
else:
return super().__getattribute__(name)
def __setattr__(self, name, value):
if name in self.form_items:
element = self.form_items[name]
form_element = element[0](self, self.find_element(*element[1]))
form_element.set_value(value)
else:
self.__dict__[name] = value

View File

@@ -10,6 +10,8 @@ from PyRIGS.tests.base import BaseTest, AutoLoginTest
from assets import models, urls from assets import models, urls
from reversion import revisions as reversion from reversion import revisions as reversion
from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from RIGS.test_functional import animation_is_finished
import datetime import datetime
@@ -256,6 +258,54 @@ class TestSupplierCreateAndEdit(AutoLoginTest):
self.assertTrue(self.page.success) self.assertTrue(self.page.success)
class TestAssetAudit(AutoLoginTest):
def setUp(self):
super().setUp()
self.category = models.AssetCategory.objects.create(name="Haulage")
self.status = models.AssetStatus.objects.create(name="Probably Fine", should_show=True)
self.supplier = models.Supplier.objects.create(name="The Bazaar")
self.connector = models.Connector.objects.create(description="Trailer Socket", current_rating=1, voltage_rating=40, num_pins=13)
models.Asset.objects.create(asset_id="1", description="Trailer Cable", status=self.status, category=self.category, date_acquired=datetime.date(2020, 2, 1))
models.Asset.objects.create(asset_id="11", description="Trailerboard", status=self.status, category=self.category, date_acquired=datetime.date(2020, 2, 1))
models.Asset.objects.create(asset_id="111", description="Erms", status=self.status, category=self.category, date_acquired=datetime.date(2020, 2, 1))
models.Asset.objects.create(asset_id="1111", description="A hammer", status=self.status, category=self.category, date_acquired=datetime.date(2020, 2, 1))
self.page = pages.AssetAuditList(self.driver, self.live_server_url).open()
def test_audit_process(self):
asset_id = "1111"
self.page.set_query(asset_id)
self.page.search()
wait = WebDriverWait(self.driver, 3)
wait.until(animation_is_finished())
mdl = self.page.modal
self.assertTrue(mdl.is_displayed)
# Do it wrong on purpose to check error display
mdl.remove_all_required()
mdl.description = ""
mdl.submit()
wait.until(animation_is_finished())
self.assertTrue(mdl.is_displayed)
self.assertIn("This field is required.", mdl.errors["Description"])
# Now do it properly
new_desc = "A BIG hammer"
mdl.description = new_desc
mdl.submit()
wait.until(animation_is_finished())
self.assertFalse(mdl.is_displayed)
# Check data is correct
audited = models.Asset.objects.get(asset_id="1111")
self.assertEqual(audited.description, new_desc)
# Make sure audit 'log' was filled out
self.assertEqual(self.profile.initials, audited.last_audited_by.initials)
self.assertEqual(datetime.datetime.now().date(), audited.last_audited_at.date())
self.assertEqual(datetime.datetime.now().hour, audited.last_audited_at.hour)
self.assertEqual(datetime.datetime.now().minute, audited.last_audited_at.minute)
# Check we've removed it from the 'needing audit' list
self.assertNotIn(asset_id, self.page.assets)
class TestSupplierValidation(TestCase): class TestSupplierValidation(TestCase):
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):