From c63b98755abb7ef371a5f32c018842d65ebbd8ee Mon Sep 17 00:00:00 2001 From: PJ Richardson <52798694+prichard77@users.noreply.github.com> Date: Tue, 19 May 2020 12:32:12 -0400 Subject: [PATCH] [1LP][RFR] Add support for create and nav_away to Host.update() and test_infrastructure_hosts_crud (#10090) * Create draft of rewrite of test_infrastructure_hosts_crud to edit only single hosts * Fix flake8 issues * Reorder imports * Removing outdated BZ lable * Add from_details kwarg to host.update * Update host.update nav to support edit from hosts view * Update Host.update to support edit from hosts view * Put view.is_displayed back into Host.update() * Add support for cancel and nav_away to Host.update() and test_infrastructure_hosts_crud * Reorder import * Move pytest.fail up into test and add support for nav_away_changes * Fix missing quote in parameter list * Add explicit kwarg to host.delete and update format of random string * Remove delete from update doc block * Updated Host.update() and test_infrastructure_hosts_crud to use kwargs instead of action strings * Update nav_away and cancel kwargs in call to Hosts.update() * Added BZ to exception log msg and added details on crud_actions to docblock * Remove newline in docblock for test_infrastructure_hosts_compare * Add comments to and rearrange structure of test_infrastructure_hosts_crud for clarity and easier understanding * Add more comments and update docblock for clarity * Update kwargs and associated logic to make from_hosts the one off exception and default to from_details * Remove nav_away and changes kwargs from Host.update() * Rewrite test_infrastructure_hosts_crud to not use parameterization of actions * Set from_details default to True in Host.update() and set it to True in cancel calls in test_infrastructure_hosts_crud * Update from_details logic and remove cancel kwarg assignements to the default value * Combine multi lines into one where applicable --- cfme/common/host_views.py | 2 +- cfme/infrastructure/host.py | 10 ++- cfme/tests/infrastructure/test_host.py | 94 ++++++++++++++++++++++---- 3 files changed, 89 insertions(+), 17 deletions(-) diff --git a/cfme/common/host_views.py b/cfme/common/host_views.py index 2c4ce26370..634208763e 100644 --- a/cfme/common/host_views.py +++ b/cfme/common/host_views.py @@ -307,7 +307,7 @@ class HostEditView(HostFormView): @property def is_displayed(self): return ( - self.logged_in_as_current_user and self.navigation.currently_selected == [ + self.in_compute_infrastructure_hosts and self.navigation.currently_selected == [ 'Compute', 'Infrastructure', 'Hosts'] and self.title.text == 'Info/Settings') diff --git a/cfme/infrastructure/host.py b/cfme/infrastructure/host.py index e2f5540222..a3ebdcfdd2 100644 --- a/cfme/infrastructure/host.py +++ b/cfme/infrastructure/host.py @@ -94,12 +94,16 @@ def __init__(self, **kwargs): super(Host.Credential, self).__init__(**kwargs) self.ipmi = kwargs.get('ipmi') - def update(self, updates, validate_credentials=False, from_details=True): + def update(self, updates, validate_credentials=False, from_details=True, cancel=False): """Updates a host in the UI. Better to use utils.update.update context manager than call this directly. Args: - updates (dict): fields that are changing. + updates (dict): fields that are changing. + validate_credentials (bool): if True, validate host credentials + from_details (bool): if True, select 'Edit Selected items' from details view + else, select 'Edit Selected items' from hosts view + cancel (bool): click cancel button to cancel the edit if True """ if from_details: view = navigate_to(self, "Edit") @@ -137,7 +141,7 @@ def update(self, updates, validate_credentials=False, from_details=True): view.endpoints.ipmi.validate_button.click() view.flash.assert_no_error() changed = any([changed, credentials_changed, ipmi_credentials_changed]) - if changed: + if changed and not cancel: view.save_button.click() logger.debug("Trying to save update for host with id: %s", str(self.get_db_id)) view = self.create_view(HostDetailsView) diff --git a/cfme/tests/infrastructure/test_host.py b/cfme/tests/infrastructure/test_host.py index a38dc783c9..2b47bd0977 100644 --- a/cfme/tests/infrastructure/test_host.py +++ b/cfme/tests/infrastructure/test_host.py @@ -4,10 +4,12 @@ import fauxfactory import pytest from wait_for import TimedOutError +from widgetastic.exceptions import UnexpectedAlertPresentException from cfme import test_requirements from cfme.base.credential import Credential from cfme.common.host_views import HostsEditView +from cfme.common.host_views import HostsView from cfme.common.provider_views import InfraProviderDetailsView from cfme.common.provider_views import ProviderNodesView from cfme.fixtures.provider import setup_or_skip @@ -86,7 +88,6 @@ def navigate_and_select_quads(provider): Returns: view: the provider nodes view, quadicons already selected""" - # TODO: prichard navigate instead of creating views and consider creaing EditableMixin hosts_view = navigate_to(provider, 'ProviderNodes') assert hosts_view.is_displayed [h.ensure_checked() for h in hosts_view.entities.get_all()] @@ -462,6 +463,8 @@ def test_infrastructure_hosts_compare(appliance, setup_provider_min_hosts, provi casecomponent: Infra caseimportance: high initialEstimate: 1/6h + Bugzilla: + 1746214 """ h_coll = locals()[hosts_collection].collections.hosts @@ -487,6 +490,7 @@ def test_infrastructure_hosts_navigation_after_download_from_compare( initialEstimate: 1/3h Bugzilla: 1747545 + """ h_coll = locals()[hosts_collection].collections.hosts hosts_view = h_coll.compare_entities(entities_list=h_coll.all()[:num_hosts]) @@ -526,26 +530,90 @@ def test_add_ipmi_refresh(appliance, setup_provider): @test_requirements.infra_hosts -@pytest.mark.parametrize("crud_action", ['edit_from_hosts', 'edit_from_details', 'remove']) -def test_infrastructure_hosts_crud(appliance, setup_provider, crud_action): +@pytest.mark.meta(automates=[1634794]) +def test_infrastructure_hosts_crud(appliance, setup_provider): """ Polarion: assignee: prichard casecomponent: Infra caseimportance: low initialEstimate: 1/6h + Bugzilla: + 1634794 """ host = appliance.collections.hosts.all()[0] - if crud_action != 'remove': - stamp = fauxfactory.gen_alphanumeric() - new_custom_id = f'Edit host data. {stamp}' - with update(host, from_details=(crud_action == 'edit_from_details')): - host.custom_ident = new_custom_id + # Case1 - edit from Hosts + new_custom_id = f'Edit host data. {fauxfactory.gen_alphanumeric()}' + with update(host, from_details=False): + host.custom_ident = new_custom_id + # verify edit + assert navigate_to(host, 'Details').entities.summary("Properties").get_text_of( + "Custom Identifier") == new_custom_id + + # Case2 - edit from Details + new_custom_id = f'Edit host data. {fauxfactory.gen_alphanumeric()}' + with update(host, from_details=True): + host.custom_ident = new_custom_id + # verify edit + assert navigate_to(host, 'Details').entities.summary("Properties").get_text_of( + "Custom Identifier") == new_custom_id + + # Case3 - canceling the edit + # get the existing value + try: + existing_custom_id = navigate_to(host, 'Details').entities.summary( + "Properties").get_text_of("Custom Identifier") + except NameError: + existing_custom_id = None + # start edit and cancel + new_custom_id = f'Edit host data. {fauxfactory.gen_alphanumeric()}' + with update(host, from_details=True, cancel=True): + host.custom_ident = new_custom_id + # verify edit + # No changes are expected. Comparing to existing value captured above. + try: + assert navigate_to(host, 'Details').entities.summary("Properties").get_text_of( + "Custom Identifier") == existing_custom_id + except NameError: + if existing_custom_id: + raise - assert host.custom_ident == new_custom_id + # Case4 - navigate away from edit view before making any updates in UI. + view = navigate_to(host, "Edit") + # navigate away before any changes have been made in the edit view + try: + view.navigation.select('Compute', 'Infrastructure', 'Hosts', handle_alert=False) + except UnexpectedAlertPresentException as e: + if "Abandon changes" in e.msg: + pytest.fail("Abandon changes alert displayed, but no changes made. BZ1634794") + else: + raise + view = host.create_view(HostsView) + assert view.is_displayed + # No changes are expected. Comparing to existing value captured above. + try: assert navigate_to(host, 'Details').entities.summary("Properties").get_text_of( - "Custom Identifier") == new_custom_id - else: - host.delete() - host.delete(cancel=False) + "Custom Identifier") == existing_custom_id + except NameError: + if existing_custom_id: + raise + + # Case5 -Nav away from edit view after making updates in UI(not saved). + new_custom_id = f'Edit host data. {fauxfactory.gen_alphanumeric()}' + view = navigate_to(host, "Edit") + view.fill({"custom_ident": new_custom_id}) + # navigate away here after changes have been made in the edit view(not saved) + view = navigate_to(host.parent, "All") + assert view.is_displayed + # No changes are expected. Comparing to existing value captured above. + try: + assert navigate_to(host, 'Details').entities.summary("Properties").get_text_of( + "Custom Identifier") == existing_custom_id + except NameError: + if existing_custom_id: + raise + + # Case6 - lastly do the delete. First try is canceled. + host.delete(cancel=True) + host.delete