Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CV UI - Promote, Publish, Add Content #939

Merged
merged 10 commits into from
Oct 17, 2024
113 changes: 113 additions & 0 deletions airgun/entities/contentview_new.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import time

from navmazing import NavigateToSibling
from wait_for import wait_for

from airgun.entities.base import BaseEntity
from airgun.navigation import NavigateStep
from airgun.navigation import navigator
from airgun.utils import retry_navigation
from airgun.views.contentview_new import NewContentViewCreateView
# from airgun.views.contentview_new import NewContentViewDeleteView
from airgun.views.contentview_new import NewContentViewEditView
from airgun.views.contentview_new import NewContentViewTableView
from airgun.views.contentview_new import NewContentViewVersionPromote
from airgun.views.contentview_new import NewContentViewVersionPublishView


class NewContentViewEntity(BaseEntity):
Expand All @@ -22,6 +29,57 @@ def search(self, value):
view = self.navigate_to(self, 'All')
return view.search(value)

def publish(self, entity_name, values=None):
"""Publishes to create new version of CV and promotes the contents to
'Library' environment.
:return: dict with new content view version table row; contains keys
like 'Version', 'Status', 'Environments' etc.
"""
view = self.navigate_to(self, 'Publish', entity_name=entity_name)
if values:
view.fill(values)
view.next.click()
view.finish.click()
view.progressbar.wait_for_result()
view = self.navigate_to(self, 'Edit', entity_name=entity_name)
return view.versions.table.read()

def promote(self, entity_name, version_name, lce_name):
"""Promotes the selected version of content view to given environment.
:return: dict with new content view version table row; contains keys
like 'Version', 'Status', 'Environments' etc.
"""
view = self.navigate_to(self, 'Promote', entity_name=entity_name, version_name=version_name)
modal = NewContentViewVersionPromote(self.browser)
if modal.is_displayed:
modal.lce.fill({lce_name: True})
modal.promote.click()
view = self.navigate_to(self, 'Edit', entity_name=entity_name)
view.versions.search(version_name)
return view.versions.table.row(version=version_name).read()

def publish_and_promote(self, entity_name, lce_name, values=None):
view = self.navigate_to(self, 'Publish', entity_name=entity_name)
if values:
view.fill(values)
view.lce(lce_name).fill(True)
view.next.click()
view.next.click()
view.progressbar.wait_for_result()
view = self.navigate_to(self, 'Edit', entity_name=entity_name)
return view.versions.table.read()

def update(self, entity_name, values):
"""Update existing content view"""
view = self.navigate_to(self, 'Edit', entity_name=entity_name)
# need a wait to recognize the loading is complete
# sleep works for now
time.sleep(3)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no hard sleep!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was the old me omkar, I can fix it :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

returning to this: have tried various other things, and the sleep is the only thing consistently working

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say keep it then if there is no other way.
As I believe in many cases there is unfortunately none. :/

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And then I would remove # sleep works for now comment :)

filled_values = view.fill(values)
view.flash.assert_no_error()
view.flash.dismiss()
return filled_values


@navigator.register(NewContentViewEntity, 'All')
class ShowAllContentViewsScreen(NavigateStep):
Expand All @@ -34,6 +92,24 @@ def step(self, *args, **kwargs):
self.view.menu.select('Content', 'Lifecycle', 'Content Views')


@navigator.register(NewContentViewEntity, 'Edit')
class EditContentView(NavigateStep):
"""Navigate to Edit Content View screen.
Args:
entity_name: name of content view
"""

VIEW = NewContentViewEditView

def prerequisite(self, *args, **kwargs):
return self.navigate_to(self.obj, 'All')

def step(self, *args, **kwargs):
entity_name = kwargs.get('entity_name')
self.parent.search(entity_name)
self.parent.table.row(name=entity_name)['Name'].widget.click()


@navigator.register(NewContentViewEntity, 'New')
class CreateContentView(NavigateStep):
"""Navigate to Create content view."""
Expand All @@ -44,3 +120,40 @@ class CreateContentView(NavigateStep):

def step(self, *args, **kwargs):
self.parent.create_content_view.click()


@navigator.register(NewContentViewEntity, 'Publish')
class PublishContentViewVersion(NavigateStep):
"""Navigate to Content View Publish screen.
Args:
entity_name: name of content view
"""

VIEW = NewContentViewVersionPublishView

def prerequisite(self, *args, **kwargs):
"""Open Content View first."""
return self.navigate_to(self.obj, 'Edit', entity_name=kwargs.get('entity_name'))

def step(self, *args, **kwargs):
"""Click 'Publish new version' button"""
self.parent.publish.click()


@navigator.register(NewContentViewEntity, 'Promote')
class PromoteContentViewVersion(NavigateStep):
"""Navigate to Content View Promote screen.
Args:
entity_name: name of content view
version_name: name of content view version to promote
"""

VIEW = NewContentViewEditView

def prerequisite(self, *args, **kwargs):
return self.navigate_to(self.obj, 'Edit', entity_name=kwargs.get('entity_name'))

def step(self, *args, **kwargs):
version_name = kwargs.get('version_name')
self.parent.versions.search(version_name)
self.parent.versions.table[0][7].widget.item_select('Promote')
99 changes: 99 additions & 0 deletions airgun/views/common.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import time

from wait_for import wait_for
from widgetastic.widget import Checkbox
from widgetastic.widget import ConditionalSwitchableView
from widgetastic.widget import do_not_read_this_widget
Expand All @@ -13,6 +16,8 @@
from widgetastic_patternfly import TabWithDropdown
from widgetastic_patternfly4.navigation import Navigation
from widgetastic_patternfly4.ouia import Dropdown
from widgetastic_patternfly4.ouia import PatternflyTable
from widgetastic_patternfly4.ouia import Button as PF4Button

from airgun.utils import get_widget_by_name
from airgun.utils import normalize_dict_values
Expand All @@ -22,6 +27,7 @@
from airgun.widgets import GenericRemovableWidgetItem
from airgun.widgets import ItemsList
from airgun.widgets import LCESelector
from airgun.widgets import PF4LCESelector
from airgun.widgets import Pf4ConfirmationDialog
from airgun.widgets import PF4Search
from airgun.widgets import ProgressBar
Expand Down Expand Up @@ -259,6 +265,33 @@ def read(self):
return self.lce.read()


class PF4LCESelectorGroup(LCESelectorGroup):
"""Group of :class:`airgun.widgets.PF4LCESelector`, typically present on page
for selecting desired lifecycle environment.

Usage::

lce = View.nested(PF4LCESelectorGroup)

#or

@View.nested
class lce(PF4LCESelectorGroup):
pass
"""

ROOT = (
".//*[self::div or self::span][@class='env-path']/parent::*"
)

PARAMETERS = ('lce_name',)

LAST_ENV = ".//*[self::div or self::span][@class='env-path'][last()]"
lce = PF4LCESelector(
locator=ParametrizedLocator(""".//label[contains(@class, 'pf-c-check__label')][normalize-space(.)='{lce_name}']""")
)


class ListRemoveTab(SatSecondaryTab):
"""'List/Remove' tab, part of :class:`AddRemoveResourcesView`."""

Expand Down Expand Up @@ -364,6 +397,72 @@ def read(self):
}


class NewAddRemoveResourcesView(View):
searchbox = PF4Search()
type = Dropdown(
locator='.//div[contains(@class, "All repositories") or'
' contains(@aria-haspopup="listbox")]'
)
Status = Dropdown(
locator='.//div[contains(@class, "All") or contains(@aria-haspopup="listbox")]'
)
add_repo = PF4Button('OUIA-Generated-Button-secondary-2')
# Need to add kebab menu
table = PatternflyTable(
component_id='OUIA-Generated-Table-4',
column_widgets={
0: Checkbox(locator='.//input[@type="checkbox"]'),
'Type': Text('.//a'),
'Name': Text('.//a'),
'Product': Text('.//a'),
'Sync State': Text('.//a'),
'Content': Text('.//a'),
'Status': Text('.//a'),
},
)

def search(self, value):
"""Search for specific available resource and return the results"""
self.searchbox.search(value)
# Tried following ways to wait for table to be displayed, only sleep worked
# Might need a before/after fill
wait_for(
lambda: self.table.is_displayed is True,
timeout=60,
delay=1,
)
time.sleep(3)
self.table.wait_displayed()
return self.table.read()

def add(self, value):
"""Associate specific resource"""
self.search(value)
next(self.table.rows())[0].widget.fill(True)
self.add_repo.click()

def fill(self, values):
"""Associate resource(s)"""
if not isinstance(values, list):
values = list((values,))
for value in values:
self.add(value)

def remove(self, value):
"""Unassign some resource(s).
:param str or list values: string containing resource name or a list of
such strings.
"""
self.search(value)
next(self.table.rows())[0].widget.fill(True)
self.remove_button.click()

def read(self):
"""Read all table values from both resource tables"""
return self.table.read()



class AddRemoveSubscriptionsView(AddRemoveResourcesView):
"""A variant of :class:`AddRemoveResourcesView` for managing subscriptions.
Subscriptions table has different structure - entity label is located in
Expand Down
Loading