综合平台编程器项目的远程存储
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 

157 行
5.9 KiB

  1. #include "domain/project_storage.h"
  2. #include "domain/register_repository.h"
  3. #include "services/hmi_editor_service.h"
  4. #include "services/hmi_runtime_service.h"
  5. #include "services/project_service.h"
  6. #include "services/runtime_mode_service.h"
  7. #include "ui/hmi_editor_widget.h"
  8. #include "ui/main_window.h"
  9. #include <QAction>
  10. #include <QApplication>
  11. #include <QDockWidget>
  12. #include <QLabel>
  13. #include <QLineEdit>
  14. #include <iostream>
  15. #include <stdexcept>
  16. #include <string>
  17. namespace {
  18. class TestProjectStorage final : public ProjectStorage
  19. {
  20. public:
  21. // 主窗口测试使用无副作用存储实现,隔离文件对 UI 行为的影响
  22. ProjectSaveResult save(const Project &, const std::string &) override
  23. {
  24. return {true, ProjectStorageError::None, {}};
  25. }
  26. ProjectLoadResult load(const std::string &) override
  27. {
  28. return {false, {}, ProjectStorageError::FileReadFailed, {}};
  29. }
  30. };
  31. void require(bool condition, const std::string &message)
  32. {
  33. if (!condition)
  34. {
  35. throw std::runtime_error(message);
  36. }
  37. }
  38. template<typename ObjectType>
  39. ObjectType *requiredChild(MainWindow &window, const char *name)
  40. {
  41. // 通过 objectName 取得 Designer 组件,缺失时给出明确测试失败信息
  42. ObjectType *child = window.findChild<ObjectType *>(QString::fromLatin1(name));
  43. require(child != nullptr, std::string("missing UI object ") + name);
  44. return child;
  45. }
  46. void testModeActionsControlEditingAvailability()
  47. {
  48. // 验证模式动作会同步禁用编辑入口,并在失败时恢复当前选择
  49. TestProjectStorage storage;
  50. ProjectService project_service(storage);
  51. HmiEditorService editor_service(project_service);
  52. VirtualRegisterRepository repository;
  53. HmiRuntimeService runtime_service(repository);
  54. RuntimeModeService mode_service;
  55. MainWindow window(
  56. mode_service, project_service, editor_service, runtime_service);
  57. window.resize(1000, 640);
  58. window.show();
  59. QApplication::processEvents();
  60. QAction *editing_action = requiredChild<QAction>(window, "editingModeAction");
  61. QAction *offline_action = requiredChild<QAction>(window, "offlineModeAction");
  62. QAction *online_action = requiredChild<QAction>(window, "onlineModeAction");
  63. QAction *add_button_action = requiredChild<QAction>(window, "addButtonAction");
  64. QAction *delete_control_action = requiredChild<QAction>(window, "deleteControlAction");
  65. QDockWidget *project_dock = requiredChild<QDockWidget>(window, "projectDock");
  66. QDockWidget *properties_dock = requiredChild<QDockWidget>(window, "propertiesDock");
  67. QLabel *selection = requiredChild<QLabel>(window, "selectionValueLabel");
  68. QLineEdit *text_edit = requiredChild<QLineEdit>(window, "controlTextEdit");
  69. HmiEditorWidget *hmi_editor = requiredChild<HmiEditorWidget>(
  70. window, "hmiEditorWidget");
  71. const qreal compact_scale = hmi_editor->transform().m11();
  72. window.resize(1600, 900);
  73. QApplication::processEvents();
  74. require(hmi_editor->transform().m11() > compact_scale,
  75. "HMI page must refit when the window becomes larger");
  76. require(editing_action->isChecked(), "editing action must be selected initially");
  77. require(project_dock->isEnabled(), "project dock must be enabled while editing");
  78. require(properties_dock->isEnabled(), "properties dock must be enabled while editing");
  79. add_button_action->trigger();
  80. const std::string page_id = editor_service.firstPageId();
  81. require(editor_service.findPage(page_id)->controls.size() == 1,
  82. "adding a control must update the HMI page model");
  83. require(selection->text() == QStringLiteral("button-1"),
  84. "selecting an added control must update the property panel");
  85. require(text_edit->text() == QStringLiteral("按钮"),
  86. "property panel must show the control text");
  87. delete_control_action->trigger();
  88. require(editor_service.findPage(page_id)->controls.empty(),
  89. "deleting a selected control must update the HMI page model");
  90. offline_action->trigger();
  91. require(mode_service.mode() == ApplicationMode::OfflineRunning,
  92. "offline action must enter offline running");
  93. require(!project_dock->isEnabled(),
  94. "project dock must be disabled while running");
  95. require(!properties_dock->isEnabled(),
  96. "properties dock must be disabled while running");
  97. require(!add_button_action->isEnabled(),
  98. "HMI add controls must be disabled while running");
  99. online_action->trigger();
  100. require(mode_service.mode() == ApplicationMode::OfflineRunning,
  101. "running modes must not switch directly through the UI");
  102. require(offline_action->isChecked(),
  103. "failed mode changes must restore the active action");
  104. editing_action->trigger();
  105. require(mode_service.mode() == ApplicationMode::Editing,
  106. "editing action must return to editing");
  107. require(project_dock->isEnabled(),
  108. "project dock must be restored after returning to editing");
  109. require(properties_dock->isEnabled(),
  110. "properties dock must be restored after returning to editing");
  111. require(add_button_action->isEnabled(),
  112. "HMI add controls must be restored after returning to editing");
  113. online_action->trigger();
  114. require(mode_service.mode() == ApplicationMode::Editing,
  115. "online action must require an initial PLC read");
  116. require(editing_action->isChecked(),
  117. "rejected online running must restore the editing action");
  118. }
  119. } // namespace
  120. int main(int argc, char *argv[])
  121. {
  122. // 无窗口平台使 Qt Widgets 测试可在自动化环境稳定运行
  123. qputenv("QT_QPA_PLATFORM", QByteArrayLiteral("offscreen"));
  124. QApplication application(argc, argv);
  125. try
  126. {
  127. testModeActionsControlEditingAvailability();
  128. }
  129. catch (const std::exception &error)
  130. {
  131. std::cerr << "main window tests failed: " << error.what() << '\n';
  132. return 1;
  133. }
  134. std::cout << "main window tests passed\n";
  135. return 0;
  136. }