From 64e36db5f9d2ec9d4b21d5b3bba20f1f1259a764 Mon Sep 17 00:00:00 2001 From: Shveta Sachdeva Date: Thu, 10 Dec 2020 20:48:37 -0800 Subject: [PATCH 1/3] Automate new UI for MTA --- mta/entities/__init__.py | 13 ++++++------- mta/entities/projects.py | 8 +++++--- mta/widgetastic/__init__.py | 14 ++++++++++++-- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/mta/entities/__init__.py b/mta/entities/__init__.py index b9c58a1..639f6c3 100644 --- a/mta/entities/__init__.py +++ b/mta/entities/__init__.py @@ -2,8 +2,9 @@ from wait_for import wait_for from widgetastic.widget import Text from widgetastic.widget import View -from widgetastic_patternfly import Button + from widgetastic_patternfly import Input +from widgetastic_patternfly4 import Button from mta.base.application.implementations.web_ui import MTANavigateStep from mta.base.application.implementations.web_ui import ViaWebUI @@ -37,16 +38,14 @@ def is_displayed(self): class BaseLoggedInPage(View): """This is base view for MTA""" - header = Text(locator=".//img[@id='header-logo']") + header = Text(locator=".//img[@alt='brand']") home_navigation = HOMENavigation("//ul") navigation = MTANavigation('//ul[@class="list-group"]') setting = DropdownMenu( locator=".//li[contains(@class, 'dropdown') and .//span[@class='pficon pficon-user']]" ) - help = DropdownMenu( - locator=".//li[contains(@class, 'dropdown') and .//span[@class='pficon pficon-help']]" - ) + help = Button(id="aboutButton") # only if no project available blank_state = View.nested(BlankStateView) @@ -69,12 +68,12 @@ class BaseWebUICollection(BaseCollection): class AllProjectView(BaseLoggedInPage): """This view represent Project All View""" - title = Text(".//div[contains(@class, 'projects-bar')]/h1") + title = Text(".//div[contains(@class, 'pf-c-content')]/h1") search = Input("searchValue") sort = SortSelector("class", "btn btn-default dropdown-toggle") projects = ProjectList(locator=".//div[contains(@class, 'projects-list')]") - new_project_button = Button("New Project") + new_project_button = Button("Create project") @View.nested class no_matches(View): # noqa diff --git a/mta/entities/projects.py b/mta/entities/projects.py index 0384196..7cc6087 100644 --- a/mta/entities/projects.py +++ b/mta/entities/projects.py @@ -34,8 +34,8 @@ class AddProjectView(AllProjectView): @View.nested class create_project(View): # noqa create_project = ProjectSteps("Create Project") - name = Input(name="projectTitle") - description = Input(locator='.//textarea[@id="idDescription"]') + name = Input(name="name") + description = Input(locator='.//textarea[@name="description"]') next_button = Button("Next") cancel_button = Button("Cancel") fill_strategy = WaitFillViewStrategy("20s") @@ -52,7 +52,9 @@ class add_applications(View): # noqa add_applications = ProjectSteps("Add Applications") delete_application = Text(locator=".//div[contains(@class, 'action-button')]/span/i") confirm_delete = Button("Yes") - upload_file = HiddenFileInput(id="fileUpload") + upload_file = HiddenFileInput( + locator='.//input[@accept=".ear,.har,.jar,.rar,.sar,.war,.zip"]') + next_button = Button("Next") back_button = Button("Back") cancel_button = Button("Cancel") diff --git a/mta/widgetastic/__init__.py b/mta/widgetastic/__init__.py index 93ab124..4945039 100644 --- a/mta/widgetastic/__init__.py +++ b/mta/widgetastic/__init__.py @@ -247,12 +247,12 @@ class HiddenFileInput(FileInput): """ def fill(self, filepath): - self.browser.set_attribute("style", "position", self) + self.browser.set_attribute("style", "display: none;", self) self.browser.send_keys(filepath, self) @property def is_displayed(self): - self.browser.set_attribute("style", "position", self) + self.browser.set_attribute("style", "display: none;", self) return self.browser.is_displayed(self) @@ -263,3 +263,13 @@ class AddButton(Button): def __locator__(self): return ".//button[text()='Cancel']/following-sibling::button" + + +class PF4Button(Button): + """New PF4 button has different locator + """ + + def __locator__(self): + return ( + './/*[(self::a or self::button or (self::input and (@type="button" or @type="submit")))' + '{}]'.format(self.locator_conditions)) \ No newline at end of file From 13a57f2951fa9b8ba2f4fa726eb4465f17e02baa Mon Sep 17 00:00:00 2001 From: Shveta Sachdeva Date: Fri, 11 Dec 2020 14:11:17 -0800 Subject: [PATCH 2/3] Automate new UI for MTA --- mta/entities/__init__.py | 9 +- mta/entities/projects.py | 216 ++++++++++++++++++++++++++++-------- mta/widgetastic/__init__.py | 10 -- setup.cfg | 1 + 4 files changed, 174 insertions(+), 62 deletions(-) diff --git a/mta/entities/__init__.py b/mta/entities/__init__.py index 639f6c3..38ac40f 100644 --- a/mta/entities/__init__.py +++ b/mta/entities/__init__.py @@ -2,7 +2,6 @@ from wait_for import wait_for from widgetastic.widget import Text from widgetastic.widget import View - from widgetastic_patternfly import Input from widgetastic_patternfly4 import Button @@ -19,18 +18,18 @@ class BlankStateView(View): """This view represent web-console without any project i.e. blank state""" - ROOT = ".//div[contains(@class, 'blank-slate')]" + ROOT = ".//div[contains(@class, 'pf-c-empty-state__content')]" - title = Text(locator=".//h1") + title = Text(locator=".//h4") welcome_help = Text(locator=".//div[@class='welcome-help-text']") - new_project_button = Button("New Project") + new_project_button = Button("Create project") documentation = Text(locator=".//a[contains(text(), 'documentation')]") @property def is_displayed(self): return ( self.title.is_displayed - and self.title.text == "Welcome to the Web Console." + and self.title.text == "Welcome to the Migration Toolkit for Applications" and self.new_project_button.is_displayed ) diff --git a/mta/entities/projects.py b/mta/entities/projects.py index 7cc6087..928c8f3 100644 --- a/mta/entities/projects.py +++ b/mta/entities/projects.py @@ -9,8 +9,8 @@ from widgetastic.widget import Select from widgetastic.widget import Text from widgetastic.widget import View -from widgetastic_patternfly import Button from widgetastic_patternfly import Input +from widgetastic_patternfly4 import Button from mta.base.application.implementations.web_ui import MTANavigateStep from mta.base.application.implementations.web_ui import navigate_to @@ -24,16 +24,20 @@ from mta.utils.update import Updateable from mta.widgetastic import AddButton from mta.widgetastic import HiddenFileInput -from mta.widgetastic import ProjectSteps from mta.widgetastic import TransformationPath class AddProjectView(AllProjectView): fill_strategy = WaitFillViewStrategy("15s") + create_project = Text(locator=".//h1[normalize-space(.)='Create project']") + + @property + def is_displayed(self): + return self.create_project.is_displayed @View.nested class create_project(View): # noqa - create_project = ProjectSteps("Create Project") + title = Text(locator=".//h5[normalize-space(.)='Project details']") name = Input(name="name") description = Input(locator='.//textarea[@name="description"]') next_button = Button("Next") @@ -42,18 +46,20 @@ class create_project(View): # noqa @property def is_displayed(self): - return self.name.is_displayed and self.create_project.is_displayed + return self.name.is_displayed and self.title.is_displayed def after_fill(self, was_change): self.next_button.click() @View.nested class add_applications(View): # noqa - add_applications = ProjectSteps("Add Applications") + # add_applications = ProjectSteps("Add Applications") + title = Text(locator=".//h5[normalize-space(.)='Add applications']") delete_application = Text(locator=".//div[contains(@class, 'action-button')]/span/i") confirm_delete = Button("Yes") upload_file = HiddenFileInput( - locator='.//input[@accept=".ear,.har,.jar,.rar,.sar,.war,.zip"]') + locator='.//input[@accept=".ear,.har,.jar,.rar,.sar,.war,.zip"]' + ) next_button = Button("Next") back_button = Button("Back") @@ -62,7 +68,7 @@ class add_applications(View): # noqa @property def is_displayed(self): - return self.add_applications.is_displayed + return self.title.is_displayed def fill(self, values): app_list = values.get("app_list") @@ -82,21 +88,42 @@ def after_fill(self, was_change): self.next_button.click() class configure_analysis(View): # noqa - PARAMETERS = ("pkg",) - configure_analysis = ProjectSteps("Configure the Analysis") - transformation_path = TransformationPath() - application_packages = Text( - locator=".//wu-select-packages/h3[normalize-space(.)='Application packages']" - ) - save_and_run = Button("Save & Run") - fill_strategy = WaitFillViewStrategy("15s") + @View.nested + class set_transformation_target(View): # noqa + # configure_analysis = ProjectSteps("Configure the Analysis") + title = Text(locator=".//h5[normalize-space(.)='Select transformation target']") + transformation_path = TransformationPath() + application_packages = Text( + locator=".//wu-select-packages/h3[normalize-space(.)='Application packages']" + ) + next_button = Button("Next") + back_button = Button("Back") + cancel_button = Button("Cancel") + fill_strategy = WaitFillViewStrategy("15s") - @property - def is_displayed(self): - return self.configure_analysis.is_displayed + @property + def is_displayed(self): + return self.title.is_displayed + + def fill(self, values): + """ + Args: + values: + """ + if values.get("transformation_path"): + self.transformation_path.select_card( + card_name=values.get("transformation_path") + ) + was_change = True + self.after_fill(was_change) + return was_change + + def after_fill(self, was_change): + self.next_button.click() @ParametrizedView.nested - class application_package(ParametrizedView): # noqa + class select_packages(ParametrizedView): # noqa + title = Text(locator=".//h5[normalize-space(.)='Select packages']") PARAMETERS = ("pkg",) app_checkbox = Text( @@ -117,13 +144,34 @@ class application_package(ParametrizedView): # noqa "/select/option[text()[normalize-space()={pkg|quote}]]" ) ) + next_button = Button("Next") + back_button = Button("Back") + cancel_button = Button("Cancel") + fill_strategy = WaitFillViewStrategy("15s") @property def is_displayed(self): - return self.app_checkbox.is_displayed and self.include_pkg.is_displayed - + return self.title.is_displayed + + def fill(self, values): + """ + Args: + values: + """ + if values.get("pkg"): + self.app_checkbox(values.get("pkg")).click() + was_change = True + self.after_fill(was_change) + return was_change + + def after_fill(self, was_change): + self.next_button.click() + + class advanced(View): # noqa @View.nested - class use_custom_rules(View): # noqa + class custom_rules(View): # noqa + title = Text(locator=".//h5[normalize-space(.)='Custom rules']") + expand_custom_rules = Text( locator=".//span[contains(@class ,'fa field-selection-toggle-pf')]" ) @@ -134,9 +182,32 @@ class use_custom_rules(View): # noqa rule = Text( locator=".//option[text()[normalize-space()='custom.Test1rules.rhamt.xml']]" ) + next_button = Button("Next") + back_button = Button("Back") + cancel_button = Button("Cancel") + fill_strategy = WaitFillViewStrategy("15s") + + @property + def is_displayed(self): + return self.title.is_displayed + + def fill(self, values): + """ + Args: + values: + """ + if values.get("file_rule"): + self.expand_custom_rules.click() + was_change = True + self.after_fill(was_change) + return was_change + + def after_fill(self, was_change): + self.next_button.click() @View.nested - class use_custom_labels(View): # noqa + class custom_labels(View): # noqa + title = Text(locator=".//h5[normalize-space(.)='Custom labels']") expand_custom_labels = Text( locator=".//a[text()[normalize-space(.)='Use custom labels']]" ) @@ -147,9 +218,32 @@ class use_custom_labels(View): # noqa label = Text( locator=".//option[text()[normalize-space()='customWebLogic.windup.label.xml']]" ) + next_button = Button("Next") + back_button = Button("Back") + cancel_button = Button("Cancel") + fill_strategy = WaitFillViewStrategy("15s") + + @property + def is_displayed(self): + return self.title.is_displayed + + def fill(self, values): + """ + Args: + values: + """ + if values.get("file_label"): + self.expand_custom_labels.click() + was_change = True + self.after_fill(was_change) + return was_change + + def after_fill(self, was_change): + self.next_button.click() @View.nested - class advanced_options(View): # noqa + class options(View): # noqa + title = Text(locator=".//h5[normalize-space(.)='Advanced options']") expand_advanced_options = Text( locator=".//a[text()[normalize-space(.)='Advanced options']]" ) @@ -158,31 +252,30 @@ class advanced_options(View): # noqa select_value = Checkbox(locator=".//input[@name='currentOptionInput']") add_button = Button("Add") cancel_button = Button("Cancel") - delete_button = Button("Delete") + next_button = Button("Next") + back_button = Button("Back") + fill_strategy = WaitFillViewStrategy("25s") - def fill(self, values): - """ - Args: - values: - """ - if values.get("transformation_path"): - self.transformation_path.select_card(card_name=values.get("transformation_path")) - wait_for(lambda: self.application_packages.is_displayed, delay=0.6, timeout=240) - was_change = True - self.after_fill(was_change) - return was_change + @property + def is_displayed(self): + return self.title.is_displayed + + def after_fill(self, was_change): + self.next_button.click() + + @View.nested + class review(View): # noqa + title = Text(locator=".//h5[normalize-space(.)='Review project details']") + save = Button("Save") + save_and_run = Button("Save and run") + + @property + def is_displayed(self): + return self.title.is_displayed def after_fill(self, was_change): self.save_and_run.click() - @property - def is_displayed(self): - return ( - self.create_project.is_displayed - or self.add_applications.is_displayed - or self.configure_analysis.is_displayed - ) - class DetailsProjectView(AllProjectView): run_analysis_button = Button("Run Analysis") @@ -279,7 +372,17 @@ def all(self): for p in view.projects.projects ] - def create(self, name, description=None, app_list=None, transformation_path=None): + def create( + self, + name, + description=None, + app_list=None, + transformation_path=None, + pkg=None, + file_rule=None, + file_label=None, + options=None, + ): """Create a new project. Args: @@ -287,13 +390,32 @@ def create(self, name, description=None, app_list=None, transformation_path=None description: The description of the project app_list: Applications to be analyzed transformation_path: transformation_path + pkg: package + file_rule: Rules + file_label: Label + options: Options """ view = navigate_to(self, "Add") view.create_project.fill({"name": name, "description": description}) view.add_applications.wait_displayed() view.add_applications.fill({"app_list": app_list}) - view.configure_analysis.wait_displayed() - view.configure_analysis.fill({"transformation_path": transformation_path}) + view.configure_analysis.set_transformation_target.wait_displayed() + view.configure_analysis.set_transformation_target.fill( + {"transformation_path": transformation_path} + ) + wait_for( + lambda: view.configure_analysis.select_packages(pkg).is_displayed, delay=0.2, timeout=60 + ) + view.configure_analysis.select_packages(pkg).wait_displayed() + view.configure_analysis.select_packages(pkg).fill({"pkg": pkg}) + view.advanced.custom_rules.wait_displayed() + view.advanced.custom_rules.fill({"file_rule": file_rule}) + view.advanced.custom_labels.wait_displayed() + view.advanced.custom_labels.fill({"file_label": file_label}) + view.advanced.options.wait_displayed() + view.advanced.options.fill({"options": options}) + view.review.options.wait_displayed() + view.review.after_fill(was_change=True) project = self.instantiate( name=name, diff --git a/mta/widgetastic/__init__.py b/mta/widgetastic/__init__.py index 4945039..3513740 100644 --- a/mta/widgetastic/__init__.py +++ b/mta/widgetastic/__init__.py @@ -263,13 +263,3 @@ class AddButton(Button): def __locator__(self): return ".//button[text()='Cancel']/following-sibling::button" - - -class PF4Button(Button): - """New PF4 button has different locator - """ - - def __locator__(self): - return ( - './/*[(self::a or self::button or (self::input and (@type="button" or @type="submit")))' - '{}]'.format(self.locator_conditions)) \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index a5e98c0..09af4c5 100644 --- a/setup.cfg +++ b/setup.cfg @@ -38,6 +38,7 @@ install_requires= wait_for werkzeug webdriver_kaifuku + widgetastic.core>=0.61 yaycl [options.package_data] From df3836743ec5fe9a5a96216365bc43366f6db700 Mon Sep 17 00:00:00 2001 From: Shveta Sachdeva Date: Fri, 11 Dec 2020 14:23:14 -0800 Subject: [PATCH 3/3] Automate new UI --- mta/entities/projects.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mta/entities/projects.py b/mta/entities/projects.py index 928c8f3..f8dc7ba 100644 --- a/mta/entities/projects.py +++ b/mta/entities/projects.py @@ -414,7 +414,7 @@ def create( view.advanced.custom_labels.fill({"file_label": file_label}) view.advanced.options.wait_displayed() view.advanced.options.fill({"options": options}) - view.review.options.wait_displayed() + view.review.wait_displayed() view.review.after_fill(was_change=True) project = self.instantiate(