Repository: ManageIQ/integration_tests

Issue:
Update cloud provider tests
also, 
- a implementation of update() that can be used as an example for other entities in CFME
- simple quadicon impl
- locate() interface - any object can implement locate() to return a locator for that thing.  Example, Quadicon
- Create a Provider object from config data



Discussion:
`TypeError: go_to() got an unexpected keyword argument 'context'`

Are there local navigate_ui changes that aren't on PyPI?

The test `setup of test_provider_editz` (editz?) is failing when adding the provider. I see the name get entered but the form immediately resets, erasing it, so the provider doesn't get saved.

@seandst oh hehe... i uh, forgot to publish my changes to `ui_navigate`.  Fixed.  You'll need to pip install or update or whatever to get the latest.


Resolving patch:
diff --git a/cfme/fixtures/pytest_selenium.py b/cfme/fixtures/pytest_selenium.py
--- a/cfme/fixtures/pytest_selenium.py
+++ b/cfme/fixtures/pytest_selenium.py
@@ -62,7 +62,9 @@ def elements(o):
     elif t == tuple:
         return browser().find_elements(*o)
     else:
-        raise TypeError("Don't know how to convert %s to WebElement." % o)
+        return elements(o.locate())  # if object implements locate(), try to get elements
+        # from that locator.  If it doesn't implement locate(), we're in trouble so
+        # let the error bubble up.
 
 
 def element(o):
@@ -79,7 +81,7 @@ def element(o):
     """
     matches = elements(o)
     if not matches:
-        raise NoSuchElementException("Element {} not found on page.".format(o))
+        raise NoSuchElementException("Element {} not found on page.".format(str(o)))
     return elements(o)[0]
 
 
@@ -251,21 +253,30 @@ def select_by_value(loc, text):
 
 
 def checkbox(loc, set_to=False):
-    """Checks a given checkbox
+    """
+    Checks or unchecks a given checkbox
 
     Finds an element given by loc and checks it
 
     Args:
         loc: The locator of the element
-        value: The value the checkbox should represent as a bool.
+        value: The value the checkbox should represent as a bool (or None to do nothing)
 
     Returns: None
     """
-    el = element(loc)
-    ActionChains(browser()).move_to_element(el).perform()
-    if el.is_selected() is not set_to:
-        el.click()
-        wait_for_ajax()
+    if set_to is not None:
+        el = element(loc)
+        ActionChains(browser()).move_to_element(el).perform()
+        if el.is_selected() is not set_to:
+            click(el)
+
+
+def check(loc):
+    checkbox(loc, True)
+
+
+def uncheck(loc):
+    checkbox(loc, False)
 
 
 def current_url():
diff --git a/cfme/web_ui/__init__.py b/cfme/web_ui/__init__.py
--- a/cfme/web_ui/__init__.py
+++ b/cfme/web_ui/__init__.py
@@ -815,3 +815,25 @@ def container(self, ident):
             raise exceptions.ElementOrBlockNotFound(
                 "Either the element of the block could not be found")
         return el
+
+
+class Quadicon(object):
+    ''' Represents a single quadruple icon in the CFME UI.
+
+    Args:
+       name:  The label of the icon
+    '''
+
+    def __init__(self, name):
+        self.name = name
+
+    def checkbox(self):
+        '''Returns:  a locator for the internal checkbox for the quadicon'''
+        return "//input[@type='checkbox' and ../../..//a[@title='%s']]" % self.name
+
+    def locate(self):
+        '''Returns:  a locator for the quadicon itself'''
+        return "//div[@id='quadicon' and ../../..//a[@title='%s']]" % self.name
+
+    def __str__(self):
+        return self.locate()
diff --git a/cfme/web_ui/flash.py b/cfme/web_ui/flash.py
--- a/cfme/web_ui/flash.py
+++ b/cfme/web_ui/flash.py
@@ -11,8 +11,8 @@ def __init__(self, message=None, level=None):
         self.message = message
         self.level = level
 
-    def __str__(self):
-        return "Flash % message '%'" % self.level, self.message
+    def __repr__(self):
+        return "[Flash %s message '%s']" % (self.level, self.message)
 
 
 def message(el):
@@ -22,6 +22,7 @@ def message(el):
 
 def get_messages():
     '''Return a list of flash messages'''
+    sel.wait_for_ajax()
     return map(message, sel.elements(area.message))
 
 
@@ -40,4 +41,4 @@ def assert_no_errors():
 
 def assert_message_match(m):
     if not any([fm.message == m for fm in get_messages()]):
-        raise Exception("No matching flash message for '%'" % m)
+        raise Exception("No matching flash message for '%s'" % m)


Test patch: