class RepositoryPuppetModulesView(BaseLoggedInView, SearchableViewMixin): breadcrumb = BreadCrumb() dialog = ConfirmationDialog() table = SatTable( locator=".//table", column_widgets={ 0: Checkbox( locator=".//input[@ng-change='itemSelected(item)']"), } ) select_all = Checkbox( locator=".//input[@type='checkbox'][@ng-change='allSelected()']") items_per_page = Select( locator=".//select[@ng-model='table.params.per_page']") total_puppet_modules = Text( "//span[@class='pagination-pf-items-total ng-binding']") remove_packages = Text(".//button[@ng-click='openModal()']") @property def is_displayed(self): breadcrumb_loaded = self.browser.wait_for_element( self.breadcrumb, exception=False) return ( breadcrumb_loaded and self.breadcrumb.locations[0] == 'Products' and self.breadcrumb.locations[2] == 'Repositories' and self.breadcrumb.read() == 'Manage Puppet Modules' )
class ContentCredentialEditView(BaseLoggedInView): breadcrumb = BreadCrumb() remove = Text("//button[contains(., 'Remove Content Credential')]") dialog = ConfirmationDialog() @property def is_displayed(self): breadcrumb_loaded = self.browser.wait_for_element(self.breadcrumb, exception=False) return (breadcrumb_loaded and self.breadcrumb.locations[0] == 'Content Credential' and self.breadcrumb.read() != 'New Content Credential') @View.nested class details(SatTab): name = EditableEntry(name='Name') content_type = ReadOnlyEntry(name='Type') content = EditableEntry(name='Content') products = ReadOnlyEntry(name='Products') repos = ReadOnlyEntry(name='Repositories') @View.nested class products(SatTab, SearchableViewMixin): table = Table('.//table', column_widgets={'Name': Text('./a')}) @View.nested class repositories(SatTab, SearchableViewMixin): table = Table('.//table', column_widgets={'Name': Text('./a')})
class ContentViewEditView(BaseLoggedInView): return_to_all = Text("//a[text()='Content Views']") publish = Text("//button[contains(., 'Publish New Version')]") actions = ActionsDropdown("//div[contains(@class, 'btn-group')]") dialog = ConfirmationDialog() @property def is_displayed(self): return self.browser.wait_for_element(self.return_to_all, exception=False) is not None @View.nested class Details(SatTab): name = EditableEntry(name='Name') label = ReadOnlyEntry(name='Label') description = EditableEntry(name='Description') composite = ReadOnlyEntry(name='Composite?') force_puppet = EditableEntryCheckbox(name='Force Puppet') @View.nested class yumrepo(SatTabWithDropdown): TAB_NAME = 'Yum Content' SUB_ITEM = 'Repositories' repos = View.nested(AddRemoveResourcesView)
class SyncPlanEditView(BaseLoggedInView): breadcrumb = BreadCrumb() actions = ActionsDropdown("//div[contains(@class, 'btn-group')]") dialog = ConfirmationDialog() @property def is_displayed(self): breadcrumb_loaded = self.browser.wait_for_element(self.breadcrumb, exception=False) return ( breadcrumb_loaded and self.breadcrumb.locations[0] == 'Sync Plans' and self.breadcrumb.read() != 'New Sync Plan' ) @View.nested class details(SatTab): name = EditableEntry(name='Name') description = EditableEntry(name='Description') date_time = EditableDateTime(name='Start Date') next_sync = ReadOnlyEntry(name='Next Sync') recurring_logic = ReadOnlyEntry(name='Recurring Logic') enabled = EditableEntryCheckbox(name='Sync Enabled') interval = EditableEntrySelect(name='Interval') cron_expression = EditableEntry(name='Cron Logic') products_count = ReadOnlyEntry(name='Products') @View.nested class products(SatTab): resources = View.nested(AddRemoveResourcesView)
class ContentCredentialEditView(BaseLoggedInView): return_to_all = Text("//a[text()='Content Credential']") remove = Text("//button[contains(., 'Remove Content Credential')]") dialog = ConfirmationDialog() @property def is_displayed(self): return self.browser.wait_for_element(self.return_to_all, exception=False) is not None @View.nested class details(SatTab): name = EditableEntry(name='Name') content_type = ReadOnlyEntry(name='Type') content = EditableEntry(name='Content') products = ReadOnlyEntry(name='Products') repos = ReadOnlyEntry(name='Repositories') @View.nested class products(SatTab): table = SatTable(locator=".//table") @View.nested class repositories(SatTab): table = SatTable(locator=".//table")
class HostCollectionInstallErrataView(BaseLoggedInView): title = Text("//h4[contains(., 'Content Host Errata Management')]") search = TextInput( locator=".//input[@type='text' and @ng-model='errataFilter']") refresh = Text(locator=".//button[@ng-click='fetchErrata()']") install = ActionsDropdown( "//span[contains(@class, 'btn-group')]" "[button[contains(@class, 'btn') " "and contains(@ng-click, 'showConfirm')]]" ) table = SatTable( ".//table", column_widgets={ 0: Checkbox( locator=".//input[@ng-model='erratum.selected']"), 'Id': Text(locator="./a[@ng-click='transitionToErrata(erratum)']"), } ) dialog = ConfirmationDialog() @property def is_displayed(self): """The view is displayed when it's title exists""" return self.browser.wait_for_element( self.title, exception=False) is not None
class ActivationKeyEditView(BaseLoggedInView): return_to_all = Text("//a[text()='Activation Keys']") action_list = SelectActionList() dialog = ConfirmationDialog() lce = LCESelector() @property def is_displayed(self): return self.browser.wait_for_element(self.return_to_all, exception=False) is not None
class ActivationKeyEditView(BaseLoggedInView): return_to_all = Text("//a[text()='Activation Keys']") actions = ActionsDropdown("//div[contains(@class, 'btn-group')]") dialog = ConfirmationDialog() @property def is_displayed(self): return self.browser.wait_for_element(self.return_to_all, exception=False) is not None @View.nested class details(SatTab): name = EditableEntry(name='Name') description = EditableEntry(name='Description') hosts_limit = EditableLimitEntry(name='Host Limit') service_level = EditableEntrySelect(name='Service Level') lce = ParametrizedView.nested(LCESelectorGroup) content_view = EditableEntrySelect(name='Content View') @View.nested class subscriptions(SatTab): resources = View.nested(AddRemoveSubscriptionsView) @View.nested class repository_sets(SatTab): TAB_NAME = 'Repository Sets' table = Table(locator=".//table") no_rows_message = Text( ".//table//td/span[contains(@data-block, 'no-rows-message')]") def read(self): if not self.no_rows_message.is_displayed: return self.table.read() return [] @View.nested class host_collections(SatTab): TAB_NAME = 'Host Collections' resources = View.nested(AddRemoveResourcesView) @View.nested class content_hosts(SatTabWithDropdown): TAB_NAME = 'Associations' SUB_ITEM = 'Content Hosts' table = Table(locator=".//table") no_rows_message = Text( ".//table//td/span[contains(@data-block, 'no-rows-message')]") def read(self): if not self.no_rows_message.is_displayed: return self.table.read() return []
class ProductsTableView(BaseLoggedInView, SearchableViewMixin): title = Text("//h2[contains(., 'Products')]") new = Text("//button[contains(@href, '/products/new')]") edit = Text("//td/a[contains(@ui-sref, 'product.repositories') and " "contains(@href, 'products')]") repo_discovery = Text("//button[contains(.,'Repo Discovery')]") actions = ActionsDropdown("//div[contains(@class, 'btn-group')]") dialog = ConfirmationDialog() @property def is_displayed(self): return self.browser.wait_for_element(self.title, exception=False) is not None
class ContentViewEditView(BaseLoggedInView): return_to_all = Text("//a[text()='Content Views']") publish = Text("//button[contains(., 'Publish New Version')]") action_list = SelectActionList() dialog = ConfirmationDialog() @property def is_displayed(self): return self.browser.wait_for_element(self.return_to_all, exception=False) is not None @View.nested class Details(SatTab): name = EditableEntry(name='Name') label = ReadOnlyEntry(name='Label') description = EditableEntry(name='Description') composite = ReadOnlyEntry(name='Composite?') force_puppet = EditableEntryCheckbox(name='Force Puppet')
class ContentHostsView(BaseLoggedInView, SearchableViewMixin): title = Text("//h2[contains(., 'Content Hosts')]") export = Text( ".//a[contains(@class, 'btn')][contains(@href, 'content_hosts.csv')]") register = Text(".//button[@ui-sref='content-hosts.register']") actions = ActionsDropdown(".//div[contains(@class, 'btn-group')]") dialog = ConfirmationDialog() table = SatTable('.//table', column_widgets={ 0: Checkbox(locator="./input[@type='checkbox']"), 'Name': Text('./a'), 'Subscription Status': StatusIcon(), 'Installable Updates': InstallableUpdatesCellView(), }) @property def is_displayed(self): return self.browser.wait_for_element(self.title, exception=False) is not None
class ActivationKeyEditView(BaseLoggedInView): """View for the ActivationKeys Edit page""" breadcrumb = BreadCrumb() actions = ActionsDropdown("//div[contains(@class, 'btn-group')]") dialog = ConfirmationDialog() @property def is_displayed(self): breadcrumb_loaded = self.browser.wait_for_element(self.breadcrumb, exception=False) return (breadcrumb_loaded and self.breadcrumb.locations[0] == 'Activation Keys' and self.breadcrumb.read() != 'New Activation Key') @View.nested class details(SatTab): name = EditableEntry(name='Name') description = EditableEntry(name='Description') hosts_limit = EditableLimitEntry(name='Host Limit') service_level = EditableEntrySelect(name='Service Level') lce = ParametrizedView.nested(LCESelectorGroup) content_view = EditableEntrySelect(name='Content View') @View.nested class subscriptions(SatTab): resources = View.nested(AddRemoveSubscriptionsView) @View.nested class repository_sets(SatTab): TAB_NAME = 'Repository Sets' table = Table(locator=".//table") @View.nested class host_collections(SatTab): TAB_NAME = 'Host Collections' resources = View.nested(AddRemoveResourcesView) @View.nested class content_hosts(SatTabWithDropdown): TAB_NAME = 'Associations' SUB_ITEM = 'Content Hosts' table = Table(locator=".//table")
class ProductEditView(BaseLoggedInView): breadcrumb = BreadCrumb() actions = ActionsDropdown("//div[contains(@class, 'btn-group')]") dialog = ConfirmationDialog() @property def is_displayed(self): breadcrumb_loaded = self.browser.wait_for_element(self.breadcrumb, exception=False) return (breadcrumb_loaded and self.breadcrumb.locations[0] == 'Products' and self.breadcrumb.read() not in ('New Product', 'Discover Repositories') and len(self.breadcrumb.locations) <= 3) @View.nested class details(SatTab): name = EditableEntry(name='Name') label = ReadOnlyEntry(name='Label') gpg_key = EditableEntrySelect(name='GPG Key') ssl_ca_cert = EditableEntrySelect(name='SSL CA Cert') ssl_client_cert = EditableEntrySelect(name='SSL Client Cert') ssl_client_key = EditableEntrySelect(name='SSL Client Key') description = EditableEntry(name='Description') repos_count = ReadOnlyEntry(name='Number of Repositories') tasks_count = ReadOnlyEntry(name='Active Tasks') sync_plan = EditableEntrySelect(name='Sync Plan') sync_state = ReadOnlyEntry(name='Sync State') @View.nested class repositories(SatTab): table = SatTable( locator=".//table", column_widgets={ 0: Checkbox( locator="./input[@ng-change='itemSelected(repository)']"), 'Name': Text("./a"), }, )
class RepositoriesView(BaseLoggedInView, SearchableViewMixin): breadcrumb = BreadCrumb() new = Text("//button[contains(@href, '/repositories/new')]") sync = Text("//button[contains(@ng-click, 'syncSelectedRepositories')]") delete = Text("//button[contains(@ng-show, 'canRemoveRepositories')]") dialog = ConfirmationDialog() table = SatTable( locator=".//table", column_widgets={ 0: Checkbox( locator=".//input[@ng-change='itemSelected(repository)']"), 'Name': Text("./a[contains(@ui-sref, 'product.repository.info')]"), }) @property def is_displayed(self): breadcrumb_loaded = self.browser.wait_for_element(self.breadcrumb, exception=False) return (breadcrumb_loaded and self.breadcrumb.locations[0] == 'Products' and self.breadcrumb.read() == 'Repositories')
class ActivationKeyEditView(BaseLoggedInView): return_to_all = Text("//a[text()='Activation Keys']") name = EditableEntry(name='Name') description = EditableEntry(name='Description') host_limit = EditableEntry(name='Host Limit') service_level = EditableEntrySelect(name='Service Level') action_list = SelectActionList() dialog = ConfirmationDialog() lce = LCESelector() @property def is_displayed(self): return self.browser.wait_for_element(self.return_to_all, exception=False) is not None @View.nested class subscriptions(SatTab): @View.nested class resources(AddRemoveResourcesView): checkbox_locator = ( './/table//tr[td[normalize-space(.)="%s"]]' '/following-sibling::tr//input[@type="checkbox"]')
class ProductEditView(BaseLoggedInView): return_to_all = Text("//a[text()='Products']") actions = ActionsDropdown("//div[contains(@class, 'btn-group')]") dialog = ConfirmationDialog() @property def is_displayed(self): return self.browser.wait_for_element(self.return_to_all, exception=False) is not None @View.nested class details(SatTab): name = EditableEntry(name='Name') label = ReadOnlyEntry(name='Label') gpg_key = EditableEntrySelect(name='GPG Key') ssl_ca_cert = EditableEntrySelect(name='SSL CA Cert') ssl_client_cert = EditableEntrySelect(name='SSL Client Cert') ssl_client_key = EditableEntrySelect(name='SSL Client Key') description = EditableEntry(name='Description') repos_count = ReadOnlyEntry(name='Number of Repositories') tasks_count = ReadOnlyEntry(name='Active Tasks') sync_plan = EditableEntrySelect(name='Sync Plan')
class HostCollectionEditView(BaseLoggedInView): breadcrumb = BreadCrumb() actions = ActionsDropdown("//div[contains(@class, 'btn-group')]") dialog = ConfirmationDialog() @property def is_displayed(self): breadcrumb_loaded = self.browser.wait_for_element(self.breadcrumb, exception=False) return ( breadcrumb_loaded and self.breadcrumb.locations[0] == 'Host Collections' and self.breadcrumb.read() != 'New Host Collection' ) @View.nested class details(SatTab): name = EditableEntry(name='Name') description = EditableEntry(name='Description') content_hosts = ReadOnlyEntry( locator=( ".//dt[contains(., 'Content Hosts')]/following-sibling" "::dd/a[not(contains(@class, 'ng-hide'))][1]" ) ) content_host_limit = EditableLimitEntry(name='Content Host Limit') # Package Installation, Removal, and Update manage_packages = Text(".//a[@ng-click='openPackagesModal()']") # Errata Installation install_errata = Text(".//a[@ng-click='openErrataModal()']") # Module Stream Installation, Removal, and Update manage_module_streams = Text(".//a[@ng-click='openModuleStreamsModal()']") # Change assigned Lifecycle Environment or Content View change_assigned_content = Text(".//a[@ng-click='openEnvironmentModal()']") @View.nested class hosts(SatTab): TAB_NAME = 'Hosts' resources = View.nested(AddRemoveResourcesView)
class ProductsTableView(BaseLoggedInView, SearchableViewMixin): title = Text("//h2[contains(., 'Products')]") new = Text("//button[contains(@href, '/products/new')]") edit = Text( "//td/a[contains(@ui-sref, 'product.repositories') and contains(@href, 'products')]" ) repo_discovery = Text("//button[contains(.,'Repo Discovery')]") actions = ActionsDropdown("//div[contains(@class, 'btn-group')]") table = Table( './/table', column_widgets={ 0: Checkbox(locator=".//input[@ng-change='itemSelected(product)']"), 'Name': Text('./a'), }, ) dialog = ConfirmationDialog() @property def is_displayed(self): return self.browser.wait_for_element(self.title, exception=False) is not None
class SyncPlanEditView(BaseLoggedInView): # fixme: change all return_to_all instances to use Breadcrumb widget return_to_all = Text("//a[text()='Sync Plans']") actions = ActionsDropdown("//div[contains(@class, 'btn-group')]") dialog = ConfirmationDialog() @property def is_displayed(self): return self.browser.wait_for_element(self.return_to_all, exception=False) is not None @View.nested class details(SatTab): name = EditableEntry(name='Name') description = EditableEntry(name='Description') date_time = EditableDateTime(name='Start Date') next_sync = ReadOnlyEntry(name='Next Sync') enabled = EditableEntryCheckbox(name='Sync Enabled') interval = EditableEntrySelect(name='Interval') products_count = ReadOnlyEntry(name='Products') @View.nested class products(SatTab): resources = View.nested(AddRemoveResourcesView)
class ContentHostDetailsView(BaseLoggedInView): breadcrumb = BreadCrumb() unregister = Text(".//button[@ng-click='openModal()']") dialog = ConfirmationDialog() @property def is_displayed(self): breadcrumb_loaded = self.browser.wait_for_element(self.breadcrumb, exception=False) return (breadcrumb_loaded and self.breadcrumb.locations[0] == 'Content Hosts' and len(self.breadcrumb.locations) > 1) @View.nested class details(SatTab): # Basic information name = EditableEntry(name='Name') uuid = ReadOnlyEntry(name='UUID') description = EditableEntry(name='Description') type = ReadOnlyEntry(name='Type') katello_agent = ReadOnlyEntry(name='Katello Agent') virtual_guests = ReadOnlyEntry(name='Virtual Guests') registered_through = ReadOnlyEntry(name='Registered Through') # Subscriptions subscription_status = ReadOnlyEntry(name='Subscription Status') details = ReadOnlyEntry(name='Details') auto_attach = EditableEntryCheckbox(name='Auto-Attach') service_level = EditableEntrySelect(name='Service Level') # System Purpose system_purpose_status = ReadOnlyEntry(name='System Purpose Status') service_level = EditableEntrySelect(name='Service Level (SLA)') usage_type = EditableEntrySelect(name='Usage Type') role = EditableEntrySelect(name='Role') addons = EditableEntryMultiCheckbox(name='Add ons') # Content Host Properties os = ReadOnlyEntry(name='OS') architecture = ReadOnlyEntry(name='Architecture') number_of_cpus = ReadOnlyEntry(name='Number of CPUs') sockets = ReadOnlyEntry(name='Sockets') cores_per_socket = ReadOnlyEntry(name='Cores per Socket') ram = ReadOnlyEntry(name='RAM (GB)') virtual_guest = ReadOnlyEntry(name='Virtual Guest') # Installable Errata security = ReadOnlyEntry(name='Security') bug_fix = ReadOnlyEntry(name='Bug Fix') enhancement = ReadOnlyEntry(name='Enhancement') # Content Host Content release_version = EditableEntrySelect(name='Release Version') content_view = EditableEntrySelect(name='Content View') lce = ParametrizedView.nested(LCESelectorGroup) # Content Host Status registered = ReadOnlyEntry(name='Registered') registered_by = ReadOnlyEntry(name='Registered By') last_checkin = ReadOnlyEntry(name='Last Checkin') @View.nested class provisioning_details(SatTab): TAB_NAME = 'Provisioning Details' name = ReadOnlyEntry(name='Name') status = ReadOnlyEntry(name='Status') operating_system = ReadOnlyEntry(name='Operating System') puppet_environment = ReadOnlyEntry(name='Puppet Environment') last_puppet_report = ReadOnlyEntry(name='Last Puppet Report') model = ReadOnlyEntry(name='Model') host_group = ReadOnlyEntry(name='Host Group') @View.nested class subscriptions(SatTabWithDropdown): SUB_ITEM = 'Subscriptions' status = ReadOnlyEntry(name='Status') auto_attach = EditableEntryCheckbox(name='Auto-Attach') run_auto_attach = Text(".//a[@ng-click='autoAttachSubscriptions()']") service_level = EditableEntrySelect(name='Service Level') resources = View.nested(AddRemoveSubscriptionsView) @View.nested class host_collections(SatTab): TAB_NAME = 'Host Collections' resources = View.nested(AddRemoveResourcesView) @View.nested class packages_actions(SatTabWithDropdown): TAB_NAME = 'Packages' SUB_ITEM = 'Actions' action_type = Select(name='remote_action') name = TextInput(locator='.//input[@ng-model="packageAction.term"]') perform = Button('Perform') update_all_packages = Button('Update All Packages') @View.nested class packages_installed(SatTabWithDropdown, SearchableViewMixin): TAB_NAME = 'Packages' SUB_ITEM = 'Installed' remove_selected = Button('Remove Selected') table = SatTable( './/table', column_widgets={0: Checkbox(locator="./input[@type='checkbox']")}) @View.nested class packages_applicable(SatTabWithDropdown, SearchableViewMixin): TAB_NAME = 'Packages' SUB_ITEM = 'Applicable' upgrade_selected = ActionsDropdown( ".//span[contains(@class, 'btn-group')]") update_all_packages = Button('Update All Packages') table = SatTable( './/table', column_widgets={0: Checkbox(locator="./input[@type='checkbox']")}) @View.nested class errata(SatTab): lce_filter = Select( locator='.//select[@ng-model="selectedErrataOption"]') searchbox = Search() apply_selected = ActionsDropdown( ".//span[contains(@class, 'btn-group')]") recalculate = Button('Recalculate') table = SatTable('.//table', column_widgets={ 0: Checkbox(locator="./input[@type='checkbox']"), 'Id': Text('./a'), }) def search(self, query, lce=None): """Apply available filters before proceeding with searching and automatically set proper search mask if errata id instead of errata title was passed. :param str query: search query to type into search field. Both errata id (RHEA-2012:0055) and errata title (Sea_Erratum) are supported. :param str optional lce: filter by lifecycle environment :return: list of dicts representing table rows :rtype: list """ if lce is not None: self.lce_filter.fill(lce) if re.search(r'\w{4}-\d{4}:\d{4}', query): query = 'id = {}'.format(query) self.searchbox.search(query) return self.table.read() @View.nested class module_streams(SatTab, SearchableViewMixin): TAB_NAME = 'Module Streams' status_filter = Select( locator='.//select[@ng-model="nutupaneParams.status"]') table = SatTable( locator='//table', column_widgets={ 'Name': Text('.//a'), 'Actions': ActionDropdownWithCheckbox( ".//div[contains(@class, 'dropdown')]") }, ) def search(self, query, status='All'): """Searches for Module Streams. Apply available filters before proceeding with searching. By default 'All' is passed :param str query: search query to type into search field. :param str optional status: filter by status of module stream on host :return: list of dicts representing table rows :rtype: list """ if status is not None: self.status_filter.fill(status) self.searchbox.search(query) return self.table.read() @View.nested class repository_sets(SatTab, SearchableViewMixin): TAB_NAME = 'Repository Sets' show_all = Checkbox( locator=".//input[contains(@ng-model, 'contentAccessModeAll')]") limit_to_lce = Checkbox( locator=".//input[contains(@ng-model, 'contentAccessModeEnv')]") actions = ActionsDropdown("//div[contains(@class, 'btn-group')]") table = SatTable('.//table', column_widgets={ 0: Checkbox(locator="./input[@type='checkbox']"), 'Product Name': Text('./a'), }) def read(self): """Sometimes no checkboxes are checked off by default, selecting "Show All" in such case. """ if (self.show_all.read() is False and self.limit_to_lce.read() is False): self.show_all.fill(True) return super().read()
class ContentViewEditView(BaseLoggedInView): return_to_all = Text("//a[text()='Content Views']") publish = Text("//button[contains(., 'Publish New Version')]") actions = ActionsDropdown("//div[contains(@class, 'btn-group')]") dialog = ConfirmationDialog() @property def is_displayed(self): return self.browser.wait_for_element(self.return_to_all, exception=False) is not None @View.nested class details(SatTab): name = EditableEntry(name='Name') label = ReadOnlyEntry(name='Label') description = EditableEntry(name='Description') composite = ReadOnlyEntry(name='Composite?') force_puppet = EditableEntryCheckbox(name='Force Puppet') @View.nested class versions(SatTab): searchbox = Search() table = SatTable( locator='//table', column_widgets={ 'Version': Text('.//a'), 'Status': PublishPromoteProgressBar(), 'Actions': ActionsDropdown('./div[contains(@class, "btn-group")]') }, ) def search(self, version_name): """Searches for content view version. Searchbox can't search by version name, only by id, that's why in case version name was passed, it's transformed into recognizable value before filling, for example:: 'Version 1.0' -> 'version = 1' """ search_phrase = version_name if version_name.startswith('V') and '.' in version_name: search_phrase = 'version = {}'.format( version_name.split()[1].split('.')[0]) self.searchbox.search(search_phrase) return self.table.read() @View.nested class content_views(SatTab): TAB_NAME = 'Content Views' resources = View.nested(AddRemoveResourcesView) @View.nested class repositories(SatTabWithDropdown): TAB_NAME = 'Yum Content' SUB_ITEM = 'Repositories' resources = View.nested(AddRemoveResourcesView) @View.nested class puppet_modules(SatTab): TAB_NAME = 'Puppet Modules' add_new_module = Text( './/button[@ui-sref="content-view.puppet-modules.names"]') table = SatTable('.//table')
class RepositoryEditView(BaseLoggedInView): breadcrumb = BreadCrumb() actions = ActionsDropdown("//div[contains(@class, 'btn-group')]") dialog = ConfirmationDialog() name = EditableEntry(name='Name') label = ReadOnlyEntry(name='Label') repo_type = ReadOnlyEntry(name='Type') repo_content = ConditionalSwitchableView(reference='repo_type') content_counts = SatTableWithUnevenStructure( locator='.//table[//th[normalize-space(.)="Content Type"]]', column_locator='./*' ) @repo_content.register('docker') class DockerRepository(View): registry_url = EditableEntry(name='Registry URL') upstream_repo_name = EditableEntry(name='Upstream Repository') repo_name = ReadOnlyEntry(name='Name') verify_ssl = EditableEntryCheckbox(name='Verify SSL') upstream_authorization = AuthorizationEntry( name='Upstream Authorization') publish_via_http = EditableEntryCheckbox(name='Publish via HTTP') http_proxy_policy = EditableEntrySelect(name='HTTP Proxy') proxy_policy = ConditionalSwitchableView(reference='http_proxy_policy') @proxy_policy.register(True, default=True) class NoSpecificHttpProxy(View): pass @repo_content.register('yum') class YumRepository(View): arch_restrict = EditableEntrySelect(name='Restrict to architecture') upstream_url = EditableEntry(name='Upstream URL') verify_ssl = EditableEntryCheckbox(name='Verify SSL') upstream_authorization = AuthorizationEntry( name='Upstream Authorization') metadata_type = EditableEntrySelect(name='Yum Metadata Checksum') mirror_on_sync = EditableEntryCheckbox(name='Mirror on Sync') publish_via_http = EditableEntryCheckbox(name='Publish via HTTP') gpg_key = EditableEntrySelect(name='GPG Key') download_policy = EditableEntrySelect(name='Download Policy') upload_content = FileInput(name='content[]') upload = Text("//button[contains(., 'Upload')]") http_proxy_policy = EditableEntrySelect(name='HTTP Proxy') proxy_policy = ConditionalSwitchableView(reference='http_proxy_policy') @proxy_policy.register(True, default=True) class NoSpecificHttpProxy(View): pass @repo_content.register('puppet') class PuppetRepository(View): upstream_url = EditableEntry(name='Upstream URL') verify_ssl = EditableEntryCheckbox(name='Verify SSL') upstream_authorization = AuthorizationEntry( name='Upstream Authorization') mirror_on_sync = EditableEntryCheckbox(name='Mirror on Sync') publish_via_https = ReadOnlyEntry(name='Publish via HTTPS') publish_via_http = EditableEntryCheckbox(name='Publish via HTTP') published_at = ReadOnlyEntry(name='Published At') upload_content = FileInput(name='content[]') upload = Text("//button[contains(., 'Upload')]") http_proxy_policy = EditableEntrySelect(name='HTTP Proxy') proxy_policy = ConditionalSwitchableView(reference='http_proxy_policy') @proxy_policy.register(True, default=True) class NoSpecificHttpProxy(View): pass @repo_content.register('ostree') class OstreeRepository(View): upstream_url = EditableEntry(name='Upstream URL') verify_ssl = EditableEntryCheckbox(name='Verify SSL') upstream_authorization = AuthorizationEntry( name='Upstream Authorization') publish_via_https = ReadOnlyEntry(name='Publish via HTTPS') published_at = ReadOnlyEntry(name='Published At') http_proxy_policy = EditableEntrySelect(name='HTTP Proxy') proxy_policy = ConditionalSwitchableView(reference='http_proxy_policy') @proxy_policy.register(True, default=True) class NoSpecificHttpProxy(View): pass @property def is_displayed(self): breadcrumb_loaded = self.browser.wait_for_element( self.breadcrumb, exception=False) return ( breadcrumb_loaded and self.breadcrumb.locations[0] == 'Products' # repositories do not have tabs, so if we are deep inside some # specific repository (e.g. in repository packages) - there's no # turn back, so we can't treat any level deeper than repository # details like details' sub-tab and self.breadcrumb.locations[-2] == 'Repositories' and self.breadcrumb.read() != 'New Repository' )
class ContentViewEditView(BaseLoggedInView): breadcrumb = BreadCrumb() publish = Text("//button[contains(., 'Publish New Version')]") actions = ActionsDropdown("//div[contains(@class, 'btn-group')]") dialog = ConfirmationDialog() @property def is_displayed(self): breadcrumb_loaded = self.browser.wait_for_element( self.breadcrumb, exception=False) return ( breadcrumb_loaded and self.breadcrumb.locations[0] == 'Content Views' and self.breadcrumb.read() != 'New Content View' ) @View.nested class details(SatTab): name = EditableEntry(name='Name') label = ReadOnlyEntry(name='Label') description = EditableEntry(name='Description') composite = ReadOnlyEntry(name='Composite?') force_puppet = EditableEntryCheckbox(name='Force Puppet Environment') @View.nested class versions(SatTab): searchbox = Search() table = SatTable( locator='//table', column_widgets={ 'Version': Text('.//a'), 'Status': PublishPromoteProgressBar(), 'Actions': ActionsDropdown( './div[contains(@class, "btn-group")]') }, ) def search(self, version_name): """Searches for content view version. Searchbox can't search by version name, only by id, that's why in case version name was passed, it's transformed into recognizable value before filling, for example:: 'Version 1.0' -> 'version = 1' """ search_phrase = version_name if version_name.startswith('V') and '.' in version_name: search_phrase = 'version = {}'.format( version_name.split()[1].split('.')[0]) self.searchbox.search(search_phrase) return self.table.read() @View.nested class content_views(SatTab): TAB_NAME = 'Content Views' resources = View.nested(AddRemoveResourcesView) @View.nested class repositories(SatTabWithDropdown): TAB_NAME = 'Yum Content' SUB_ITEM = 'Repositories' resources = View.nested(AddRemoveResourcesView) @View.nested class filters(SatTabWithDropdown, SearchableViewMixin): TAB_NAME = 'Yum Content' SUB_ITEM = 'Filters' new_filter = Text(".//button[@ui-sref='content-view.yum.filters.new']") remove_selected = Text(".//button[@ng-click='removeFilters()']") table = SatTable( locator='//table', column_widgets={ 0: Checkbox(locator=".//input[@type='checkbox']"), 'Name': Text('./a'), }, ) @View.nested class puppet_modules(SatTab): TAB_NAME = 'Puppet Modules' add_new_module = Text( './/button[@ui-sref="content-view.puppet-modules.names"]') table = SatTable('.//table') @View.nested class ostree_content(SatTab): TAB_NAME = 'OSTree Content' resources = View.nested(AddRemoveResourcesView)
class RepositoryEditView(BaseLoggedInView): breadcrumb = BreadCrumb() actions = ActionsDropdown("//div[contains(@class, 'btn-group')]") dialog = ConfirmationDialog() name = EditableEntry(name='Name') label = ReadOnlyEntry(name='Label') repo_type = ReadOnlyEntry(name='Type') repo_content = ConditionalSwitchableView(reference='repo_type') content_counts = SatContentCountsTable() @repo_content.register('docker') class DockerRepository(View): registry_url = EditableEntry(name='Registry URL') upstream_repo_name = EditableEntry(name='Upstream Repository') repo_name = ReadOnlyEntry(name='Name') verify_ssl = EditableEntryCheckbox(name='Verify SSL') upstream_username = EditableEntry(name='Upstream Username') upstream_password = EditableEntry(name='Upstream Password') ignore_global_proxy = EditableEntryCheckbox( name='Ignore Global HTTP Proxy') publish_via_http = EditableEntryCheckbox(name='Publish via HTTP') @repo_content.register('yum') class YumRepository(View): arch_restrict = EditableEntrySelect(name='Restrict to architecture') upstream_url = EditableEntry(name='Upstream URL') verify_ssl = EditableEntryCheckbox(name='Verify SSL') upstream_username = EditableEntry(name='Upstream Username') upstream_password = EditableEntry(name='Upstream Password') metadata_type = EditableEntrySelect(name='Yum Metadata Checksum') mirror_on_sync = EditableEntryCheckbox(name='Mirror on Sync') ignore_global_proxy = EditableEntryCheckbox( name='Ignore Global HTTP Proxy') publish_via_http = EditableEntryCheckbox(name='Publish via HTTP') gpg_key = EditableEntrySelect(name='GPG Key') download_policy = EditableEntrySelect(name='Download Policy') @repo_content.register('puppet') class PuppetRepository(View): upstream_url = EditableEntry(name='Upstream URL') verify_ssl = EditableEntryCheckbox(name='Verify SSL') upstream_username = EditableEntry(name='Upstream Username') upstream_password = EditableEntry(name='Upstream Password') mirror_on_sync = EditableEntryCheckbox(name='Mirror on Sync') ignore_global_proxy = EditableEntryCheckbox( name='Ignore Global HTTP Proxy') publish_via_https = ReadOnlyEntry(name='Publish via HTTPS') publish_via_http = EditableEntryCheckbox(name='Publish via HTTP') published_at = ReadOnlyEntry(name='Published At') @property def is_displayed(self): breadcrumb_loaded = self.browser.wait_for_element(self.breadcrumb, exception=False) return ( breadcrumb_loaded and self.breadcrumb.locations[0] == 'Products' # repositories do not have tabs, so if we are deep inside some # specific repository (e.g. in repository packages) - there's no # turn back, so we can't treat any level deeper than repository # details like details' sub-tab and self.breadcrumb.locations[-2] == 'Repositories' and self.breadcrumb.read() != 'New Repository')