CanUseLayoutMenu.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <gtest/gtest.h>
  9. #include <QPushButton>
  10. #include <QAction>
  11. #include <QtTest>
  12. #include <QMessageBox>
  13. #include <Tests/UI/MenuUIFixture.h>
  14. #include <Editor/InputDialogValidatable.h>
  15. #include <EMotionFX/CommandSystem/Source/CommandManager.h>
  16. #include <EMotionFX/Source/Actor.h>
  17. #include <EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/DockWidgetPlugin.h>
  18. #include <EMotionStudio/EMStudioSDK/Source/EMStudioPlugin.h>
  19. #include <EMotionStudio/EMStudioSDK/Source/EMStudioManager.h>
  20. #include <Editor/Plugins/SimulatedObject/SimulatedObjectWidget.h>
  21. #include <Editor/InputDialogValidatable.h>
  22. #include <Editor/Plugins/SkeletonOutliner/SkeletonOutlinerPlugin.h>
  23. #include <Tests/TestAssetCode/SimpleActors.h>
  24. #include <Tests/TestAssetCode/ActorFactory.h>
  25. #include <MCore/Source/MemoryManager.h>
  26. namespace EMotionFX
  27. {
  28. class CanUseLayoutMenuFixture
  29. : public MenuUIFixture
  30. {
  31. public:
  32. void SetUp() override
  33. {
  34. MenuUIFixture::SetUp();
  35. m_saveLayoutFileName = GenerateNewLayoutFilename();
  36. }
  37. void TearDown() override
  38. {
  39. QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
  40. if (QFile::exists(GetLayoutFilePath(GetLayoutFileName())))
  41. {
  42. QFile::remove(GetLayoutFilePath(GetLayoutFileName()));
  43. }
  44. MenuUIFixture::TearDown();
  45. }
  46. QString GetLayoutFilePath(const QString& layoutFileName) const
  47. {
  48. return QString("%1/%2.layout").arg(GetLayoutFileDirectory(), layoutFileName);
  49. }
  50. QString GetLayoutFileDirectory() const
  51. {
  52. return QDir{ QString(MysticQt::GetDataDir().c_str()) }.filePath("Layouts");
  53. }
  54. QString GetLayoutFileName()
  55. {
  56. return m_saveLayoutFileName;
  57. }
  58. QString GenerateNewLayoutFilename()
  59. {
  60. // Find a temporary layout name that doesn't already exist.
  61. bool foundFilename = false;
  62. int fileIndex = 0;
  63. while (!foundFilename)
  64. {
  65. const QString fileName = QString("TestLayout%1").arg(fileIndex);
  66. const QString filepath = GetLayoutFilePath(fileName);
  67. // If the file already exists, ask to overwrite or not.
  68. if (!QFile::exists(filepath))
  69. {
  70. return fileName;
  71. }
  72. fileIndex++;
  73. }
  74. return nullptr;
  75. }
  76. bool ComparePluginLists(const EMStudio::PluginManager::PluginVector& plugins1, const EMStudio::PluginManager::PluginVector& plugins2)
  77. {
  78. // Returns false if the lists are the same.
  79. if (plugins1.size() != plugins2.size())
  80. {
  81. return true;
  82. }
  83. for (size_t pluginIndex = 0; pluginIndex < plugins1.size(); pluginIndex++)
  84. {
  85. if (plugins1[pluginIndex] != plugins2[pluginIndex])
  86. {
  87. return true;
  88. }
  89. }
  90. return false;
  91. }
  92. void TestSaveLayoutMenuItem(const QMenu* layoutsMenu)
  93. {
  94. QAction* action = FindMenuAction(layoutsMenu, "Save Current", "LayoutsMenu");
  95. ASSERT_TRUE(layoutsMenu) << "Unable to find 'Save Current' menu option.";
  96. // Open the save dialog.
  97. action->trigger();
  98. // Set the save name and press OK.
  99. EMStudio::InputDialogValidatable* inputDialog = EMStudio::GetLayoutManager()->GetSaveLayoutNameDialog();
  100. inputDialog->SetText(GetLayoutFileName());
  101. QList<QPushButton*> dialogButtons = inputDialog->findChildren<QPushButton*>();
  102. for (QPushButton* dialogButton : dialogButtons)
  103. {
  104. if (dialogButton->text().endsWith("OK"))
  105. {
  106. QTest::mouseClick(dialogButton, Qt::LeftButton);
  107. break;
  108. }
  109. }
  110. // Check the layout file now exists
  111. const bool fileExists = QFile::exists(GetLayoutFilePath(GetLayoutFileName()));
  112. ASSERT_TRUE(fileExists) << "Failed to create layout save file";
  113. }
  114. void TestSelectNamedLayoutMenuItem(const QMenu* layoutsMenu, const QString& layoutName)
  115. {
  116. // Find the select action in the layouts menu, Specify the parent so that the corresponding remove option isn't discovered.
  117. QAction* menuAction = FindMenuAction(layoutsMenu, layoutName, "LayoutsMenu");
  118. ASSERT_TRUE(menuAction) << "Select layout menu item " << layoutName.toUtf8().data() << " not found.";
  119. // Close all plugins so we can check the load has done something.
  120. CloseAllPlugins();
  121. // Get currently active plugins;
  122. const EMStudio::PluginManager::PluginVector plugins = EMStudio::GetPluginManager()->GetActivePlugins();
  123. // Select new layout
  124. menuAction->trigger();
  125. const EMStudio::PluginManager::PluginVector newPlugins = EMStudio::GetPluginManager()->GetActivePlugins();
  126. // We're not sure what plugins should be opened, just make sure it's opened something.
  127. const bool pluginsChanged = ComparePluginLists(plugins, newPlugins);
  128. ASSERT_TRUE(pluginsChanged) << "Select layout " << layoutName.toUtf8().data() << " failed.";
  129. }
  130. void TestSelectLayoutMenuItems(const QMenu* layoutsMenu)
  131. {
  132. // Find all the layout files, there should be a menu item for each.
  133. QDir directory(GetLayoutFileDirectory());
  134. QStringList layoutFiles = directory.entryList(QStringList() << "*.layout" << "*.layout", QDir::Files);
  135. for (QString fileName : layoutFiles)
  136. {
  137. QString layoutName = fileName.replace(".layout", "");
  138. TestSelectNamedLayoutMenuItem(layoutsMenu, layoutName);
  139. }
  140. }
  141. void TestRemoveMenuItems(const QMenu* layoutsMenu)
  142. {
  143. // Only test removing the item we created: trying to remove others if they are read only will result in an assert in the error message.
  144. QAction* removeAction = FindMenuAction(layoutsMenu, GetLayoutFileName(), "RemoveMenu");
  145. ASSERT_TRUE(removeAction) << "No remove menu item found for layout " << GetLayoutFileName().toUtf8().data();
  146. removeAction->trigger();
  147. // Press "Yes" in the do you really want to delete this dialog
  148. QMessageBox* dialog = EMStudio::GetMainWindow()->GetRemoveLayoutDialog();
  149. ASSERT_TRUE(dialog);
  150. const QList<QPushButton*> dialogButtons = dialog->findChildren<QPushButton*>();
  151. for (QPushButton* dialogButton : dialogButtons)
  152. {
  153. if (dialog->buttonRole(dialogButton) == QMessageBox::YesRole)
  154. {
  155. QTest::mouseClick(dialogButton, Qt::LeftButton);
  156. }
  157. }
  158. // Check the file is now gone.
  159. bool layoutFileExists = QFile::exists(GetLayoutFilePath(GetLayoutFileName()));
  160. ASSERT_FALSE(layoutFileExists) << "Remove layout menu option failed";
  161. }
  162. private:
  163. QString m_saveLayoutFileName;
  164. };
  165. TEST_F(CanUseLayoutMenuFixture, CanUseLayoutMenu)
  166. {
  167. RecordProperty("test_case_id", "C1698603");
  168. // Find the Layouts menu.
  169. QMenu* layoutsMenu = FindMainMenuWithName("LayoutsMenu");
  170. ASSERT_TRUE(layoutsMenu) << "Unable to find layouts menu.";
  171. // First test the save current item, so that it's included in the select and remove tests.
  172. TestSaveLayoutMenuItem(layoutsMenu);
  173. TestSelectLayoutMenuItems(layoutsMenu);
  174. TestRemoveMenuItems(layoutsMenu);
  175. }
  176. } // namespace EMotionFX