예제 #1
0
    def create(self, cancel=False):
        """Create new keypair"""
        def refresh():
            self.provider.refresh_provider_relationships()
            view.browser.selenium.refresh()
            view.flush_widget_cache()

        view = navigate_to(self, 'Add')
        view.form.fill({'name': self.name,
                        'public_key': self.public_key,
                        'provider': self.provider.name})
        if cancel:
            view.form.cancel.click()
            flash_message = 'Add of new Key Pair was cancelled by the user'
        else:
            view.form.add.click()
            flash_message = VersionPick({
                Version.lowest(): 'Creating Key Pair {}'.format(self.name),
                '5.8': 'Key Pair "{}" created'.format(self.name)}).pick(self.appliance.version)

        # add/cancel should redirect, new view
        view = self.create_view(KeyPairAllView)
        # TODO BZ 1444520 causing ridiculous redirection times after submitting the form
        wait_for(lambda: view.is_displayed, fail_condition=False, num_sec=120, delay=3,
                 fail_func=lambda: view.flush_widget_cache(), handle_exception=True)
        view = self.create_view(KeyPairAllView)
        view.entities.flash.assert_no_error()
        view.entities.flash.assert_success_message(flash_message)
def pytest_generate_tests(metafunc):
    """
    Build a list of tuples containing (group_name, context)
    Returns:
        tuple containing (group_name, context)
        where group_name is a string and context is ViaUI/SSUI
    """
    appliance = find_appliance(metafunc)
    parameter_list = []
    id_list = []
    # TODO: Include SSUI role_access dict and VIASSUI context
    role_access_ui = VersionPick({
        Version.lowest(): role_access_ui_58z,
        '5.9': role_access_ui_59z,
        '5.10': role_access_ui_510z
    }).pick(appliance.version)
    logger.info('Using the role access dict: %s', role_access_ui)
    roles_and_context = [(
        role_access_ui, ViaUI)
    ]
    for role_access, context in roles_and_context:
        for group in role_access.keys():
            parameter_list.append((group, role_access, context))
            id_list.append('{}-{}'.format(group, context))
    metafunc.parametrize('group_name, role_access, context', parameter_list)
예제 #3
0
    def all(self):
        # containers table has ems_id, join with ext_mgmgt_systems on id for provider name
        # Then join with container_groups on the id for the pod
        # TODO Update to use REST API instead of DB queries
        container_table = self.appliance.db.client['containers']
        ems_table = self.appliance.db.client['ext_management_systems']
        pod_table = self.appliance.db.client['container_groups']
        container_pod_id = (
            VersionPick({
                Version.lowest(): getattr(container_table, 'container_definition_id', None),
                '5.9': getattr(container_table, 'container_group_id', None)})
            .pick(self.appliance.version))
        container_query = (
            self.appliance.db.client.session
                .query(container_table.name, pod_table.name, ems_table.name)
                .join(ems_table, container_table.ems_id == ems_table.id)
                .join(pod_table, container_pod_id == pod_table.id))
        if self.filters.get('archived'):
            container_query = container_query.filter(container_table.deleted_on.isnot(None))
        if self.filters.get('active'):
            container_query = container_query.filter(container_table.deleted_on.is_(None))
        provider = None
        # filtered
        if self.filters.get('provider'):
            provider = self.filters.get('provider')
            container_query = container_query.filter(ems_table.name == provider.name)
        containers = []
        for name, pod_name, ems_name in container_query.all():
            containers.append(
                self.instantiate(name=name, pod=pod_name,
                                 provider=provider or get_crud_by_name(ems_name)))

        return containers
예제 #4
0
 def is_displayed(self):
     title = VersionPicker({
         Version.lowest(): '{name} (All VM Templates)'.format(name=self.context['object'].name),
         '5.10': '{name} (All VM Templates and Images)'.format(name=self.context['object'].name),
     }).pick(self.extra.appliance.version)
     return (self.logged_in_as_current_user and
             self.navigation.currently_selected == ['Compute', 'Infrastructure', 'Providers'] and
             self.title.text == title)
예제 #5
0
def ProviderEntity():  # noqa
    """ Temporary wrapper for Provider Entity during transition to JS based Entity

    """
    return VersionPick({
        Version.lowest(): NonJSProviderEntity,
        '5.9': JSProviderEntity,
    })
예제 #6
0
 def parent_provider(self):
     """ Return object of parent cloud provider """
     view = navigate_to(self, 'Details')
     parent_cloud_text = VersionPick({Version.lowest(): 'Parent ems cloud',
                                      '5.10': 'Parent Cloud Provider'}
                                     ).pick(self.appliance.version)
     provider_name = view.entities.relationships.get_text_of(parent_cloud_text)
     return providers.get_crud_by_name(provider_name)
예제 #7
0
def HostEntity():  # noqa
    """ Temporary wrapper for Host Entity during transition to JS based Entity

    """
    return VersionPick({
        Version.lowest(): NonJSHostEntity,
        '5.9': JSBaseEntity,
    })
예제 #8
0
 def before_filling(self):
     item_type = self.context['object'].provider_type or \
         self.context['object'].item_type or 'Generic'
     if item_type == 'AnsibleTower':
         item_type = VersionPick({
             Version.lowest(): "AnsibleTower",
             "5.9": "Ansible Tower"
         })
     self.select_item_type.select_by_visible_text(item_type)
     self.flush_widget_cache()
예제 #9
0
    def delete(self, cancel=False, wait=False):
        view = navigate_to(self, 'Details')
        # TODO: get rid of this resolve when widgetastic.core/pull/68 is merged
        item_name = VersionPick({Version.lowest(): 'Remove this Key Pair',
                                '5.9': 'Remove this Key Pair from Inventory'}
                                ).pick(self.appliance.version)
        view.toolbar.configuration.item_select(item_name,
                                               handle_alert=(not cancel))
        # cancel doesn't redirect, confirmation does
        view.flush_widget_cache()
        if cancel:
            view = self.create_view(KeyPairDetailsView)
        else:
            view = self.create_view(KeyPairAllView)
        wait_for(lambda: view.is_displayed, fail_condition=False, num_sec=10, delay=1)

        # flash message only displayed if it was deleted
        if not cancel:
            view.flash.assert_no_error()
            view.flash.assert_success_message('Delete initiated for 1 Key Pair')

        if wait:
            def refresh():
                self.provider.refresh_provider_relationships()
                view.browser.refresh()
                view.flush_widget_cache()

            view = navigate_to(self.parent, 'All')

            wait_for(
                lambda: self.name in view.entities.all_entity_names,
                message="Wait keypairs to disappear",
                fail_condition=True,
                num_sec=300,
                delay=5,
                fail_func=refresh
            )
예제 #10
0
    def delete(self, cancel=False, wait=False):
        view = navigate_to(self, 'Details')
        # TODO: get rid of this resolve when widgetastic.core/pull/68 is merged
        item_name = VersionPick({Version.lowest(): 'Remove this Key Pair',
                                '5.9': 'Remove this Key Pair from Inventory'}
                                ).pick(self.appliance.version)
        view.toolbar.configuration.item_select(item_name,
                                               handle_alert=(not cancel))
        # cancel doesn't redirect, confirmation does
        view.flush_widget_cache()
        if cancel:
            view = self.create_view(KeyPairDetailsView)
        else:
            view = self.create_view(KeyPairAllView)
        wait_for(lambda: view.is_displayed, fail_condition=False, num_sec=10, delay=1)

        # flash message only displayed if it was deleted
        if not cancel:
            view.flash.assert_no_error()
            view.flash.assert_success_message('Delete initiated for 1 Key Pair')

        if wait:
            def refresh():
                self.provider.refresh_provider_relationships()
                view.browser.refresh()
                view.flush_widget_cache()

            view = navigate_to(self.parent, 'All')

            wait_for(
                lambda: self.name in view.entities.all_entity_names,
                message="Wait keypairs to disappear",
                fail_condition=True,
                num_sec=300,
                delay=5,
                fail_func=refresh
            )
예제 #11
0
    def create(self, cancel=False):
        """Create new keypair"""
        def refresh():
            self.provider.refresh_provider_relationships()
            view.browser.selenium.refresh()
            view.flush_widget_cache()

        view = navigate_to(self, 'Add')
        view.form.fill({
            'name': self.name,
            'public_key': self.public_key,
            'provider': self.provider.name
        })
        if cancel:
            view.form.cancel.click()
            flash_message = 'Add of new Key Pair was cancelled by the user'
        else:
            view.form.add.click()
            flash_message = VersionPick({
                Version.lowest():
                'Creating Key Pair {}'.format(self.name),
                '5.8':
                'Key Pair "{}" created'.format(self.name)
            }).pick(self.appliance.version)

        # add/cancel should redirect, new view
        view = self.create_view(KeyPairAllView)
        # TODO BZ 1444520 causing ridiculous redirection times after submitting the form
        wait_for(lambda: view.is_displayed,
                 fail_condition=False,
                 num_sec=120,
                 delay=3,
                 fail_func=lambda: view.flush_widget_cache(),
                 handle_exception=True)
        view = self.create_view(KeyPairAllView)
        view.entities.flash.assert_no_error()
        view.entities.flash.assert_success_message(flash_message)
예제 #12
0
 class retirement(Tab):  # noqa
     # TODO Somehow need to handle a modal window
     copy_from_provisioning = Button("Copy from provisioning")
     repository = BootstrapSelect("retirement_repository_id")
     playbook = BootstrapSelect("retirement_playbook_id")
     machine_credential = BootstrapSelect(
         "retirement_machine_credential_id")
     cloud_type = BootstrapSelect("retirement_cloud_type")
     cloud_credential = BootstrapSelect("retirement_cloud_credential_id")
     localhost = Input(id="retirement_inventory_localhost")
     specify_host_values = Input(id="retirement_inventory_specify")
     hosts = Input("retirement_inventory")
     logging_output = BootstrapSelect("retirement_log_output")
     max_ttl = Input("retirement_execution_ttl")
     escalate_privilege = BootstrapSwitch("retirement_become_enabled")
     verbosity = BootstrapSelect("retirement_verbosity")
     remove_resources = VersionPick({
         Version.lowest():
         BootstrapSelect("vm.catalogItemModel.retirement_remove_resources"),
         "5.9":
         BootstrapSelect(
             "vm.vm.catalogItemModel.retirement_remove_resources")
     })
     extra_vars = AnsibleExtraVariables(tab="retirement")
예제 #13
0
class ContainerAllView(ContainerObjectAllBaseView):
    """Containers All view"""
    summary = Text(VersionPick({
        Version.lowest(): '//h3[normalize-space(.) = {}]'.format(quote('All Containers')),
        '5.8': '//h1[normalize-space(.) = {}]'.format(quote('Containers'))
    }))
    containers = Table(locator="//div[@id='list_grid']//table")

    @View.nested
    class Filters(Accordion):  # noqa
        ACCORDION_NAME = "Filters"

        @View.nested
        class Navigation(VerticalNavigation):
            DIV_LINKS_MATCHING = './/div/ul/li/a[contains(text(), {txt})]'

            def __init__(self, parent, logger=None):
                VerticalNavigation.__init__(self, parent, '#Container_def_searches', logger=logger)

        tree = ManageIQTree()

    @property
    def is_displayed(self):
        return self.summary.is_displayed
예제 #14
0
class ImageRegistryDetailsView(ContainerObjectDetailsBaseView):
    """Container Image Registries Detail view"""
    SUMMARY_TEXT = VersionPick({
        Version.lowest(): 'Image Registries',
        '5.9': 'Container Image Registries'
    })
예제 #15
0
 class MyView(View):
     widget = TextInput(id=VersionPick({
         Version.lowest(): 'nonexisting',
         '1.0.0': 'input1'
     }))
예제 #16
0
class RequestsToolbar(View):
    """Toolbar on the requests view"""
    reload = Button(title=VersionPick({
        Version.lowest(): 'Reload the current display',
        '5.9': 'Refresh this page'
    }))
예제 #17
0
class TowerExplorerSystemJobTemplatesToolbar(View):
    reload = Button(title=VersionPick({Version.lowest(): 'Reload current display',
                                       '5.9': 'Refresh this page'}))
    policy = Dropdown('Policy')
    download = Dropdown('Download')
    view_selector = View.nested(ItemsToolBarViewSelector)
예제 #18
0
class RouteAllView(ContainerObjectAllBaseView):
    """Container Routes All view"""
    SUMMARY_TEXT = VersionPick({
        Version.lowest(): 'Routes',
        '5.9': 'Container Routes'
    })
예제 #19
0
 def container_provider_edit_view_class(self):
     return VersionPick({
         Version.lowest(): ContainerProviderEditView,
         '5.9': ContainerProviderEditViewUpdated
     })
예제 #20
0
 def view_classes(self):
     return VersionPick({
         Version.lowest(): RetirementView,
         "5.9": RetirementViewWithOffset
     })
예제 #21
0
class PodAllView(ContainerObjectAllBaseView):
    """Container Pods All view"""
    SUMMARY_TEXT = VersionPick({
        Version.lowest(): 'Pods',
        '5.9': 'Container Pods'
    })
예제 #22
0
class Inputs(View, ClickableMixin):
    ROOT = './/button[@id="exp_collapse_img"]/i'
    INDIRECT = True  # TODO: This appear to upset the parent lookup combined with ParView

    @property
    def is_opened(self):
        return 'fa-angle-up' in self.browser.classes(self)

    def child_widget_accessed(self, widget):
        if not self.is_opened:
            self.click()

    @ParametrizedView.nested
    class inputs(ParametrizedView):  # noqa
        PARAMETERS = ('name', )
        ROOT = ParametrizedLocator(
            '//tr[./td[2]/input[normalize-space(@value)={name|quote}]]')
        ALL_FIELDS = '//div[@id="inputs_div"]/table//tr/td[2]/input'

        @cached_property
        def row_id(self):
            attr = self.browser.get_attribute(
                'id',
                './/td/input[contains(@id, "fields_name_")]',
                parent=self)
            return int(attr.rsplit('_', 1)[-1])

        name = Input(locator=ParametrizedLocator(
            './/td/input[contains(@id, "fields_name_{@row_id}")]'))
        data_type = Select(locator=ParametrizedLocator(
            './/td/select[contains(@id, "fields_datatype_{@row_id}")]'))
        default_value = Input(locator=ParametrizedLocator(
            './/td/input[contains(@id, "fields_value_{@row_id}")]'))

        @classmethod
        def all(cls, browser):
            results = []
            for e in browser.elements(cls.ALL_FIELDS):
                results.append((browser.get_attribute('value', e), ))
            return results

        def delete(self):
            if self.browser.product_version < '5.10':
                xpath = './/img[contains(@alt, "Click to delete this")]'
            else:
                xpath = './/a/i[contains(@class, "pficon-delete")]'
            self.browser.click(xpath, parent=self)
            try:
                del self.row_id
            except AttributeError:
                pass

    add_field = VersionPick({
        Version.lowest():
        Text('//img[@alt="Equal green"]'),
        '5.10':
        Text('//button//i[contains(@class, "fa-plus")]')
    })
    name = Input(locator='.//td/input[contains(@id, "field_name")]')
    data_type = Select(locator='.//td/select[contains(@id, "field_datatype")]')
    default_value = Input(
        locator='.//td/input[contains(@id, "field_default_value")]')
    finish_add_field = VersionPick({
        Version.lowest():
        Text('//img[@alt="Add this entry"]'),
        '5.10':
        Text('//a[@title="Add this entry"]')
    })

    def read(self):
        return self.inputs.read()

    def fill(self, value):
        keys = set(value.keys())
        value = copy(value)

        present = {key for key, _ in self.inputs.read().items()}
        to_delete = present - keys
        changed = False

        # Create the new ones
        for key in keys:
            if key not in present:
                new_value = value.pop(key)
                new_value['name'] = key
                self.add_field.click()
                super(Inputs, self).fill(new_value)
                self.finish_add_field.click()
                changed = True

        # Fill the rest as expected
        if self.inputs.fill(value):
            changed = True

        # delete unneeded
        for key in to_delete:
            self.inputs(name=key).delete()
            changed = True

        return changed
예제 #23
0
def DatastoreEntity():  # noqa
    """Temporary wrapper for Datastore Entity during transition to JS based Entity """
    return VersionPick({
        Version.lowest(): NonJSDatastoreEntity,
        '5.9': JSDatastoreEntity,
    })
예제 #24
0
 class MyView(View):
     widget = TextInput(id=VersionPick({
         Version.lowest(): "nonexisting",
         "1.0.0": "input1"
     }))
예제 #25
0
class ReplicatorAllView(ContainerObjectAllBaseView):
    """Container Replicators All view"""
    SUMMARY_TEXT = VersionPick({
        Version.lowest(): 'Replicators',
        '5.9': 'Container Replicators'
    })
예제 #26
0
def DeploymentRoleEntity():  # noqa
    """Temporary wrapper for Deployment Role Entity during transition to JS based Entity """
    return VersionPick({
        Version.lowest(): NonJSDepRoleEntity,
        '5.9': JSBaseEntity,
    })
예제 #27
0
class ReplicatorDetailsView(ContainerObjectDetailsBaseView):
    """Container Replicators Details view"""
    SUMMARY_TEXT = VersionPick({
        Version.lowest(): 'Replicators',
        '5.9': 'Container Replicators'
    })
예제 #28
0
def test_picking_works_lowest_version(basic_verpick):
    assert basic_verpick.pick(Version.lowest()) == 0
예제 #29
0
class ProjectDetailsView(ContainerObjectDetailsBaseView):
    """Container Projects Detail view"""
    SUMMARY_TEXT = VersionPick({
        Version.lowest(): 'Projects',
        '5.9': 'Container Projects'
    })
예제 #30
0
 def step(self):
     self.prerequisite_view.toolbar.configuration.item_select(
         VersionPick({
             Version.lowest(): 'Add Existing Containers Provider',
             '5.9': 'Add a new Containers Provider'
         }).pick(self.obj.appliance.version))
예제 #31
0
 class mytasks(Tab):  # noqa
     TAB_NAME = VersionPick({
         Version.lowest(): 'My VM and Container Analysis Tasks',
         '5.9': 'My Tasks'
     })
     table = Table(table_loc)
def ManageIQTree(tree_id=None):  # noqa
    return VersionPick({
        Version.lowest(): DynaTree(tree_id),
        '5.7.0.1': BootstrapTreeview(tree_id),
    })
예제 #33
0
def DeploymentRoleEntity():  # noqa
    """Temporary wrapper for Deployment Role Entity during transition to JS based Entity """
    return VersionPick({
        Version.lowest(): NonJSDepRoleEntity,
        '5.9': JSBaseEntity,
    })
예제 #34
0
 class TestForm(View):
     table = Table('#withwidgets', column_widgets={
         'Column 2': TextInput(locator='./input'),
         'Column 3': VersionPick({
             Version.lowest(): TextInput(locator='./input'),
             '2.0': None})})
예제 #35
0
 class myothertasks(Tab):  # noqa
     TAB_NAME = VersionPick({
         '5.9': 'My Tasks',
         Version.lowest(): 'My Other UI Tasks'
     })
     table = Table(table_loc)
예제 #36
0
class LoginPage(View):
    flash = FlashMessages(
        VersionPick({
            Version.lowest(): 'div#flash_text_div',
            '5.8': '//div[@class="flash_text_div"]'
        })
    )

    class details(View):  # noqa
        region = Text('.//p[normalize-space(text())="Region:"]/span')
        zone = Text('.//p[normalize-space(text())="Zone:"]/span')
        appliance = Text('.//p[normalize-space(text())="Appliance:"]/span')

    change_password = Text('.//a[normalize-space(.)="Update password"]')
    back = Text('.//a[normalize-space(.)="Back"]')
    username = Input(name='user_name')
    password = Input(name='user_password')
    new_password = Input(name='user_new_password')
    verify_password = Input(name='user_verify_password')
    login = Button(id='login')

    def show_update_password(self):
        if not self.new_password.is_displayed:
            self.change_password.click()

    def hide_update_password(self):
        if self.new_password.is_displayed:
            self.back.click()

    def login_admin(self, **kwargs):
        username = conf.credentials['default']['username']
        password = conf.credentials['default']['password']
        cred = Credential(principal=username, secret=password)
        from cfme.configure.access_control import User
        user = User(credential=cred, name='Administrator')
        return self.log_in(user, **kwargs)

    def submit_login(self, method='click_on_login'):
        if method == 'click_on_login':
            self.login.click()
        elif method == 'press_enter_after_password':
            self.browser.send_keys(Keys.ENTER, self.password)
        elif method == '_js_auth_fn':
            self.browser.execute_script('miqAjaxAuth();')
        else:
            raise ValueError('Unknown method {}'.format(method))
        if self.flash.is_displayed:
            self.flash.assert_no_error()

    def log_in(self, user, method='click_on_login'):
        self.fill({
            'username': user.credential.principal,
            'password': user.credential.secret,
        })
        self.submit_login(method)
        logged_in_view = self.browser.create_view(BaseLoggedInPage)
        if logged_in_view.logged_in:
            if user.name is None:
                name = logged_in_view.current_fullname
                self.logger.info(
                    'setting the appliance.user.name to %r because it was not specified', name)
                user.name = name
            self.extra.appliance.user = user

    def update_password(
            self, username, password, new_password, verify_password=None,
            method='click_on_login'):
        self.show_update_password()
        self.fill({
            'username': username,
            'password': password,
            'new_password': new_password,
            'verify_password': verify_password if verify_password is not None else new_password
        })
        self.submit_login(method)

    def logged_in_as_user(self, user):
        return False

    @property
    def logged_in_as_current_user(self):
        return False

    @property
    def current_username(self):
        return None

    @property
    def current_fullname(self):
        return None

    @property
    def logged_in(self):
        return not self.logged_out

    @property
    def logged_out(self):
        return self.username.is_displayed and self.password.is_displayed and self.login.is_displayed

    @property
    def is_displayed(self):
        return self.logged_out
예제 #37
0
class ExpressionEditor(View, Pretty):
    """This class enables to embed the expression in a Form.

    Args:
        show_func: Function to call to show the expression if there are more of them.
    """
    @View.nested
    class field_form_view(View):  # noqa
        type = BootstrapSelect("chosen_typ")
        field = BootstrapSelect("chosen_field")
        key = BootstrapSelect("chosen_key")
        value = Input(name="chosen_value")
        user_input = Input(name="user_input")

    @View.nested
    class field_date_form(View):  # noqa
        dropdown_select = BootstrapSelect("chosen_from_1")
        input_select_date = Calendar(name="miq_date_1_0")
        input_select_time = BootstrapSelect("miq_time_1_0")

    @View.nested
    class count_form_view(View):  # noqa
        type = BootstrapSelect("chosen_typ")
        count = BootstrapSelect("chosen_count")
        key = BootstrapSelect("chosen_key")
        value = Input(name="chosen_value")
        user_input = Input(name="user_input")

    @View.nested
    class tag_form_view(View):  # noqa
        type = BootstrapSelect("chosen_typ")
        tag = BootstrapSelect("chosen_tag")
        value = BootstrapSelect("chosen_value")
        user_input = Input(name="user_input")

    @View.nested
    class find_form_view(View):  # noqa
        type = BootstrapSelect("chosen_typ")
        field = BootstrapSelect("chosen_field")
        skey = BootstrapSelect("chosen_skey")
        value = Input(name="chosen_value")
        check = BootstrapSelect("chosen_check")
        cfield = BootstrapSelect("chosen_cfield")
        ckey = BootstrapSelect("chosen_ckey")
        cvalue = Input(name="chosen_cvalue")

    @View.nested
    class registry_form_view(View):  # noqa
        type = BootstrapSelect("chosen_typ")
        key = Input(name="chosen_regkey")
        value = Input(name="chosen_regval")
        operation = BootstrapSelect("chosen_key")
        contents = Input(name="chosen_value")

    @View.nested
    class date_specific_form_view(View):  # noqa
        date = Calendar(name="miq_date_1_0")
        time = BootstrapSelect("miq_time_1_0")

    @View.nested
    class date_relative_form_view(View):  # noqa
        from_ = BootstrapSelect("chosen_from_1")
        through = BootstrapSelect("chosen_through_1")

    ROOT = "//div[@id='exp_editor_div']"
    MAKE_BUTTON = "//span[not(contains(@style,'none'))]//img[@alt='{}']"
    ATOM_ROOT = "./div[@id='exp_atom_editor_div']"
    EXPRESSIONS_ROOT = "./fieldset/div"
    COMMIT = VersionPick({
        Version.lowest():
        "//img[@alt='Commit expression element changes']",
        "5.7.1":
        Button(title="Commit expression element changes"),
    })
    DISCARD = VersionPick({
        Version.lowest():
        "//img[@alt='Discard expression element changes']",
        "5.7.1":
        Button(title="Discard expression element changes"),
    })
    REMOVE = VersionPick({
        Version.lowest(): ("//span[not(contains(@style, 'none'))]/"
                           "/img[@alt='Remove this expression element']"),
        "5.8":
        Button(title="Remove this expression element"),
    })
    NOT = VersionPick({
        Version.lowest():
        ("//span[not(contains(@style, 'none'))]"
         "//img[@alt='Wrap this expression element with a NOT']"),
        "5.8":
        Button(title="Wrap this expression element with a NOT"),
    })
    OR = VersionPick({
        Version.lowest(): ("//span[not(contains(@style, 'none'))]/"
                           "/img[@alt='OR with a new expression element']"),
        "5.8":
        Button(title="OR with a new expression element"),
    })
    AND = VersionPick({
        Version.lowest(): ("//span[not(contains(@style, 'none'))]/"
                           "/img[@alt='AND with a new expression element']"),
        "5.8":
        Button(title="AND with a new expression element"),
    })
    REDO = VersionPick({
        Version.lowest(): "//img[@alt='Redo']",
        "5.8": Button(title="Redo the last change"),
    })
    UNDO = VersionPick({
        Version.lowest(): "//img[@alt='Undo']",
        "5.8": Button(title="Undo the last change"),
    })
    SELECT_SPECIFIC = "//img[@alt='Click to change to a specific Date/Time format']"
    SELECT_RELATIVE = "//img[@alt='Click to change to a relative Date/Time format']"

    pretty_attrs = ['show_loc']

    def __init__(self, parent, show_loc=None, logger=None):
        View.__init__(self, parent, logger=logger)
        self.show_loc = show_loc

    def __locator__(self):
        return self.ROOT

    def click_undo(self):
        self.browser.click(self.UNDO)

    def click_redo(self):
        self.browser.click(self.REDO)

    def click_and(self):
        self.browser.click(self.AND)

    def click_or(self):
        self.browser.click(self.OR)

    def click_not(self):
        self.browser.click(self.NOT)

    def click_remove(self):
        self.browser.click(self.REMOVE)

    def click_commit(self):
        self.browser.click(self.COMMIT)

    def click_discard(self):
        self.browser.click(self.DISCARD)

    def click_switch_to_relative(self):
        self.browser.click(self.SELECT_RELATIVE)

    def click_switch_to_specific(self):
        self.browser.click(self.SELECT_SPECIFIC)

    @property
    def _atom_root(self):
        return self.browser.element(self.ATOM_ROOT)

    @property
    def _expressions_root(self):
        return self.browser.element(self.EXPRESSIONS_ROOT)

    def select_first_expression(self):
        """There is always at least one (???), so no checking of bounds."""
        self.browser.elements("//a[contains(@id,'exp_')]",
                              parent=self._expressions_root)[0].click()

    def select_expression_by_text(self, text):
        self.browser.click(
            "//a[contains(@id,'exp_')][contains(normalize-space(text()),'{}')]"
            .format(text))

    def no_expression_present(self):
        els = self.browser.elements("//a[contains(@id,'exp_')]",
                                    parent=self._expressions_root)
        if len(els) > 1:
            return False
        return els[0].text.strip() == "???"

    def any_expression_present(self):
        return not self.no_expression_present()

    def is_editing(self):
        try:
            self.browser.element(
                "//a[contains(@id,'exp_')][contains(normalize-space(text()),'???')]",
                parent=self._expressions_root)
            return True
        except NoSuchElementException:
            return False

    def delete_whole_expression(self):
        while self.any_expression_present():
            self.select_first_expression()
            self.click_remove()

    def read(self):
        """Returns whole expression as represented visually."""
        return self._expressions_root.text.encode("utf-8").strip()

    def enable_editor(self):
        try:
            el = self.browser.element(self.show_loc)
            wait_for(lambda: el.is_displayed, num_sec=2, delay=0.2)
            el.click()
        except (TimedOutError, NoSuchElementException):
            pass

    def fill(self, expression):
        if self.show_loc is not None:
            self.enable_editor()
        prog = create_program(expression, self)
        before = self._expressions_root.text.encode("utf-8").strip()
        prog()
        after = self._expressions_root.text.encode("utf-8").strip()
        return before != after

    def fill_count(self, count=None, key=None, value=None):
        """ Fills the 'Count of' type of form.

        If the value is unspecified and we are in the advanced search form (user input),
        the user_input checkbox will be checked if the value is None.

        Args:
            count: Name of the field to compare (Host.VMs, ...).
            key: Operation to do (=, <, >=, ...).
            value: Value to check against.
        Returns: See :py:func:`cfme.web_ui.fill`.
        """
        view = self.count_form_view
        view.fill(dict(type="Count of", count=count, key=key, value=value))
        # In case of advanced search box
        if view.user_input.is_displayed:
            user_input = value is None
            view.user_input.fill(user_input)
        self.click_commit()

    def fill_tag(self, tag=None, value=None):
        """ Fills the 'Tag' type of form.

        Args:
            tag: Name of the field to compare.
            value: Value to check against.
        """
        view = self.tag_form_view
        view.fill(dict(type="Tag", tag=tag, value=value))
        # In case of advanced search box
        if view.user_input.is_displayed:
            user_input = value is None
            view.user_input.fill(user_input)
        self.click_commit()

    def fill_registry(self,
                      key=None,
                      value=None,
                      operation=None,
                      contents=None):
        """ Fills the 'Registry' type of form."""
        view = self.registry_form_view
        view.fill(
            dict(
                type="Registry",
                key=key,
                value=value,
                operation=operation,
                contents=contents,
            ))
        self.click_commit()

    def fill_find(self,
                  field=None,
                  skey=None,
                  value=None,
                  check=None,
                  cfield=None,
                  ckey=None,
                  cvalue=None):
        view = self.find_form_view
        view.fill(
            dict(type="Find",
                 field=field,
                 skey=skey,
                 value=value,
                 check=check,
                 cfield=cfield,
                 ckey=ckey,
                 cvalue=cvalue))
        self.click_commit()

    def fill_field(self, field=None, key=None, value=None):
        """ Fills the 'Field' type of form.

        Args:
            tag: Name of the field to compare (Host.VMs, ...).
            key: Operation to do (=, <, >=, IS NULL, ...).
            value: Value to check against.
        Returns: See :py:func:`cfme.web_ui.fill`.
        """
        field_norm = field.strip().lower()
        if ("date updated" in field_norm or "date created" in field_norm
                or "boot time" in field_norm or "timestamp" in field_norm):
            no_date = False
        else:
            no_date = True
        view = self.field_form_view
        view.fill(
            dict(
                type="Field",
                field=field,
                key=key,
                value=value if no_date else None,
            ))
        # In case of advanced search box
        if view.user_input.is_displayed:
            user_input = value is None
            view.user_input.fill(user_input)
        if not no_date:
            # Flip the right part of form
            view = self.field_date_form
            if (isinstance(value, basestring)
                    and not re.match(r"^[0-9]{2}/[0-9]{2}/[0-9]{4}$", value)):
                if not view.dropdown_select.is_displayed:
                    self.click_switch_to_relative()
                view.fill({"dropdown_select": value})
                self.click_commit()
            else:
                # Specific selection
                if not view.input_select_date.is_displayed:
                    self.click_switch_to_specific()
                if (isinstance(value, tuple)
                        or isinstance(value, list)) and len(value) == 2:
                    date, time = value
                elif isinstance(value,
                                basestring):  # is in correct format mm/dd/yyyy
                    # Date only (for now)
                    date = value[:]
                    time = None
                else:
                    raise TypeError(
                        "fill_field expects a 2-tuple (date, time) or string with date"
                    )
                # TODO datetime.datetime support
                view.input_select_date.fill(date)
                # Try waiting a little bit for time field
                # If we don't wait, committing the expression will glitch
                try:
                    wait_for(lambda: view.input_select_time.is_displayed,
                             num_sec=6)
                    # It appeared, so if the time is to be set, we will set it
                    # (passing None glitches)
                    if time:
                        view.input_select_time.fill(time)
                except TimedOutError:
                    # Did not appear, ignore that
                    pass
                finally:
                    # And finally, commit the expression :)
                    self.click_commit()
        else:
            self.click_commit()
예제 #38
0
class RouteDetailsView(ContainerObjectDetailsBaseView):
    """Container Routes Detail view"""
    SUMMARY_TEXT = VersionPick({
        Version.lowest(): 'Routes',
        '5.9': 'Container Routes'
    })
예제 #39
0
class ImageRegistryAllView(ContainerObjectAllBaseView):
    """Container Images Registries All view"""
    SUMMARY_TEXT = VersionPick({
        Version.lowest(): 'Image Registries',
        '5.9': 'Container Image Registries'
    })
예제 #40
0
 def view_classes(self):
     return VersionPick({
         Version.lowest(): RetirementView,
         "5.9": RetirementViewWithOffset
     })
예제 #41
0
 class form(TimeProfileForm):  # noqa
     add = Button(VersionPick({Version.lowest(): 'Save', '5.9': 'Add'}))
예제 #42
0
def DatastoreEntity():  # noqa
    """Temporary wrapper for Datastore Entity during transition to JS based Entity """
    return VersionPick({
        Version.lowest(): NonJSDatastoreEntity,
        '5.9': JSDatastoreEntity,
    })
예제 #43
0
파일: tasks.py 프로젝트: LaVLaS/cfme_tests
class TasksView(BaseLoggedInPage):
    # Toolbar
    delete = Dropdown(
        'Delete Tasks')  # dropdown just has icon, use element title
    reload = Button(title=VersionPick({
        Version.lowest(): 'Reload the current display',
        '5.9': 'Refresh this page'
    }))

    @View.nested
    class tabs(View):  # noqa
        # Extra Toolbar
        # Only on 'All' type tabs, but for access it doesn't make sense to access the tab for a
        # toolbar button
        cancel = Button(title='Cancel the selected task')

        # Form Buttons
        apply = Button('Apply')
        reset = Button('Reset')
        default = Button('Default')

        # Filters
        zone = BootstrapSelect(id='chosen_zone')
        period = BootstrapSelect(id='time_period')
        user = BootstrapSelect(id='user_choice')
        # This checkbox search_root captures all the filter options
        # It will break for status if/when there is second checkbox selection field added
        # It's the lowest level div with an id that captures the status checkboxes
        status = CheckboxSelect(search_root='tasks_options_div')
        state = BootstrapSelect(id='state_choice')

        @View.nested
        class mytasks(Tab):  # noqa
            TAB_NAME = VersionPick({
                Version.lowest(): 'My VM and Container Analysis Tasks',
                '5.9': 'My Tasks'
            })
            table = Table(table_loc)

        @View.nested
        class myothertasks(Tab):  # noqa
            TAB_NAME = VersionPick({
                '5.9': 'My Tasks',
                Version.lowest(): 'My Other UI Tasks'
            })
            table = Table(table_loc)

        @View.nested
        class alltasks(Tab):  # noqa
            TAB_NAME = VersionPick({
                '5.9':
                'All Tasks',
                Version.lowest():
                "All VM and Container Analysis Tasks"
            })
            table = Table(table_loc)

        @View.nested
        class allothertasks(Tab):  # noqa
            TAB_NAME = "All Other Tasks"
            table = Table(table_loc)

    @property
    def is_displayed(self):
        return (self.tabs.mytasks.is_displayed
                and self.tabs.myothertasks.is_displayed
                and self.tabs.alltasks.is_displayed
                and self.tabs.allothertasks.is_displayed)