ScriptEvent_AddRemoveMethod_UpdatesInSC.py 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. """
  2. Copyright (c) Contributors to the Open 3D Engine Project.
  3. For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. SPDX-License-Identifier: Apache-2.0 OR MIT
  5. """
  6. import os
  7. from PySide2 import QtWidgets, QtTest, QtCore
  8. from editor_python_test_tools.utils import TestHelper as helper
  9. from editor_python_test_tools.utils import Report
  10. import pyside_utils
  11. import azlmbr.legacy.general as general
  12. import azlmbr.editor as editor
  13. import azlmbr.bus as bus
  14. import azlmbr.paths as paths
  15. from scripting_utils.scripting_constants import (SCRIPT_CANVAS_UI, ASSET_EDITOR_UI, NODE_PALETTE_UI, SCRIPT_EVENT_UI,
  16. NODE_PALETTE_QT, EVENTS_QT, NODE_TEST_METHOD, DEFAULT_SCRIPT_EVENT,
  17. TREE_VIEW_QT, DEFAULT_METHOD_NAME, SAVE_STRING, WAIT_TIME_3)
  18. class Tests():
  19. new_event_created = ("New Script Event created", "New Script Event not created")
  20. child_1_created = ("Initial Child Event created", "Initial Child Event not created")
  21. child_2_created = ("Second Child Event created", "Second Child Event not created")
  22. file_saved = ("Script event file saved", "Script event file did not save")
  23. method_added = ("Method added to scriptevent file", "Method not added to scriptevent file")
  24. method_removed = ("Method removed from scriptevent file", "Method not removed from scriptevent file")
  25. FILE_PATH = os.path.join(paths.projectroot, "TestAssets", "test_file.scriptevents")
  26. NUM_TEST_METHODS = 2
  27. class TestScriptEvent_AddRemoveMethod_UpdatesInSC():
  28. """
  29. Summary:
  30. Method can be added/removed to an existing .scriptevents file
  31. Expected Behavior:
  32. The Method is correctly added/removed to the asset, and Script Canvas nodes are updated accordingly.
  33. Test Steps:
  34. 1) Open Asset Editor and Script Canvas windows
  35. 2) Initially create new Script Event file with one method
  36. 3) Verify if file is created and saved
  37. 4) Add a new child element
  38. 5) Update MethodNames and save file
  39. 6) Verify if the new node exist in SC (search in node palette)
  40. 7) Delete one method and save
  41. 8) Verify if the node is removed in SC
  42. 9) Close Asset Editor
  43. Note:
  44. - This test file must be called from the Open 3D Engine Editor command terminal
  45. - Any passed and failed tests are written to the Editor.log file.
  46. Parsing the file or running a log_monitor are required to observe the test results.
  47. :return: None
  48. """
  49. def __init__(self):
  50. self.editor_window = None
  51. self.asset_editor = None
  52. self.asset_editor_widget = None
  53. self.asset_editor_row_container = None
  54. self.asset_editor_pulldown_menu = None
  55. self.script_canvas = None
  56. self.node_palette = None
  57. self.node_palette_tree = None
  58. self.node_palette_search_frame = None
  59. self.node_palette_search_box = None
  60. def initialize_asset_editor_qt_objects(self):
  61. self.asset_editor = self.editor_window.findChild(QtWidgets.QDockWidget, ASSET_EDITOR_UI)
  62. self.asset_editor_widget = self.asset_editor.findChild(QtWidgets.QWidget, "AssetEditorWindowClass")
  63. self.asset_editor_row_container = self.asset_editor_widget.findChild(QtWidgets.QWidget, "ContainerForRows")
  64. self.asset_editor_pulldown_menu = self.asset_editor_widget.findChild(QtWidgets.QMenuBar)
  65. def initialize_sc_qt_objects(self):
  66. self.script_canvas = self.editor_window.findChild(QtWidgets.QDockWidget, SCRIPT_CANVAS_UI)
  67. if self.script_canvas.findChild(QtWidgets.QDockWidget, NODE_PALETTE_QT) is None:
  68. action = pyside_utils.find_child_by_pattern(self.script_canvas, {"text": NODE_PALETTE_UI, "type": QtWidgets.QAction})
  69. action.trigger()
  70. self.node_palette = self.script_canvas.findChild(QtWidgets.QDockWidget, NODE_PALETTE_QT)
  71. self.node_palette_tree = self.node_palette.findChild(QtWidgets.QTreeView, TREE_VIEW_QT)
  72. self.node_palette_search_frame = self.node_palette.findChild(QtWidgets.QFrame, "searchFrame")
  73. self.node_palette_search_box = self.node_palette_search_frame.findChild(QtWidgets.QLineEdit, "searchFilter")
  74. def save_file(self):
  75. editor.AssetEditorWidgetRequestsBus(bus.Broadcast, "SaveAssetAs", FILE_PATH)
  76. action = pyside_utils.find_child_by_pattern(self.asset_editor_pulldown_menu, {"type": QtWidgets.QAction, "iconText": SAVE_STRING})
  77. action.trigger()
  78. # wait till file is saved, to validate that check the text of QLabel at the bottom of the AssetEditor,
  79. # if there are no unsaved changes we will not have any * in the text
  80. label = self.asset_editor.findChild(QtWidgets.QLabel, "textEdit")
  81. return helper.wait_for_condition(lambda: "*" not in label.text(), WAIT_TIME_3)
  82. def expand_container_rows(self, object_name):
  83. children = self.asset_editor_row_container.findChildren(QtWidgets.QFrame, object_name)
  84. for child in children:
  85. check_box = child.findChild(QtWidgets.QCheckBox)
  86. if check_box and not check_box.isChecked():
  87. QtTest.QTest.mouseClick(check_box, QtCore.Qt.LeftButton, QtCore.Qt.NoModifier)
  88. def node_palette_search(self, node_name):
  89. self.node_palette_search_box.setText(node_name)
  90. helper.wait_for_condition(lambda: self.node_palette_search_box.text() == node_name, WAIT_TIME_3)
  91. QtTest.QTest.keyClick(self.node_palette_search_box, QtCore.Qt.Key_Enter, QtCore.Qt.NoModifier)
  92. @pyside_utils.wrap_async
  93. async def run_test(self):
  94. # Preconditions
  95. general.idle_enable(True)
  96. # 1) Open Asset Editor
  97. # Initially close the Asset Editor and then reopen to ensure we don't have any existing assets open
  98. general.close_pane(ASSET_EDITOR_UI)
  99. general.open_pane(ASSET_EDITOR_UI)
  100. helper.wait_for_condition(lambda: general.is_pane_visible(ASSET_EDITOR_UI), WAIT_TIME_3)
  101. self.editor_window = pyside_utils.get_editor_main_window()
  102. # 2) Initially create new Script Event file with one method
  103. self.initialize_asset_editor_qt_objects()
  104. action = pyside_utils.find_child_by_pattern(self.asset_editor_pulldown_menu, {"type": QtWidgets.QAction, "text": SCRIPT_EVENT_UI})
  105. action.trigger()
  106. result = helper.wait_for_condition(
  107. lambda: self.asset_editor_row_container.findChild(QtWidgets.QFrame, EVENTS_QT) is not None
  108. and self.asset_editor_row_container.findChild(QtWidgets.QFrame, EVENTS_QT).findChild(QtWidgets.QToolButton, "") is not None,
  109. WAIT_TIME_3,
  110. )
  111. Report.result(Tests.new_event_created, result)
  112. # Add new method
  113. add_event = self.asset_editor_row_container.findChild(QtWidgets.QFrame, EVENTS_QT).findChild(QtWidgets.QToolButton, "")
  114. add_event.click()
  115. result = helper.wait_for_condition(
  116. lambda: self.asset_editor_widget.findChild(QtWidgets.QFrame, DEFAULT_SCRIPT_EVENT) is not None, WAIT_TIME_3
  117. )
  118. Report.result(Tests.child_1_created, result)
  119. # 3) Verify if file is created and saved
  120. file_saved = self.save_file()
  121. result = helper.wait_for_condition(lambda: os.path.exists(FILE_PATH), WAIT_TIME_3)
  122. Report.result(Tests.file_saved, result and file_saved)
  123. # 4) Add a new child element
  124. add_event = self.asset_editor_row_container.findChild(QtWidgets.QFrame, EVENTS_QT).findChild(QtWidgets.QToolButton, "")
  125. add_event.click()
  126. result = helper.wait_for_condition(
  127. lambda: len(self.asset_editor_widget.findChildren(QtWidgets.QFrame, DEFAULT_SCRIPT_EVENT)) == NUM_TEST_METHODS,
  128. NUM_TEST_METHODS * WAIT_TIME_3
  129. )
  130. Report.result(Tests.child_2_created, result)
  131. # 5) Update MethodNames and save file, (update all Method names to make it easier to search in SC later)
  132. # Expand the EventName initially
  133. self.expand_container_rows(DEFAULT_SCRIPT_EVENT)
  134. # Expand Name fields under it
  135. self.expand_container_rows("Name")
  136. count = 0 # 2 Method names will be updated Ex: test_method_name_0, test_method_name_1
  137. container = self.asset_editor_widget.findChild(QtWidgets.QWidget, "ContainerForRows")
  138. children = container.findChildren(QtWidgets.QFrame, "Name")
  139. for child in children:
  140. line_edit = child.findChild(QtWidgets.QLineEdit)
  141. if line_edit and line_edit.text() == DEFAULT_METHOD_NAME:
  142. line_edit.setText(f"{NODE_TEST_METHOD}_{count}")
  143. count += 1
  144. self.save_file()
  145. # 6) Verify if the new node exist in SC (search in node palette)
  146. general.open_pane(SCRIPT_CANVAS_UI)
  147. helper.wait_for_condition(lambda: general.is_pane_visible(SCRIPT_CANVAS_UI), WAIT_TIME_3)
  148. self.initialize_sc_qt_objects()
  149. self.node_palette_search(f"{NODE_TEST_METHOD}_1")
  150. method_result_1 = helper.wait_for_condition(
  151. lambda: pyside_utils.find_child_by_pattern(self.node_palette_tree, {"text": f"{NODE_TEST_METHOD}_1"}) is not None, WAIT_TIME_3)
  152. Report.result(Tests.method_added, method_result_1)
  153. # 7) Delete one method and save
  154. self.initialize_asset_editor_qt_objects()
  155. for child in container.findChildren(QtWidgets.QFrame, DEFAULT_SCRIPT_EVENT):
  156. if child.findChild(QtWidgets.QToolButton, ""):
  157. child.findChild(QtWidgets.QToolButton, "").click()
  158. break
  159. self.save_file()
  160. # 8) Verify if the node is removed in SC (search in node palette)
  161. self.initialize_sc_qt_objects()
  162. self.node_palette_search(f"{NODE_TEST_METHOD}_0")
  163. method_result_0 = helper.wait_for_condition(
  164. lambda: pyside_utils.find_child_by_pattern(self.node_palette_tree, {"text": f"{NODE_TEST_METHOD}_0"}) is None, WAIT_TIME_3)
  165. Report.result(Tests.method_removed, method_result_0)
  166. # 9) Close Asset Editor
  167. general.close_pane(ASSET_EDITOR_UI)
  168. general.close_pane(SCRIPT_CANVAS_UI)
  169. test = TestScriptEvent_AddRemoveMethod_UpdatesInSC()
  170. test.run_test()