1 /**
2 * UGENE - Integrated Bioinformatics Tools.
3 * Copyright (C) 2008-2021 UniPro <ugene@unipro.ru>
4 * http://ugene.net
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 */
21
22 #include <GTUtilsMdi.h>
23 #include <primitives/GTTabWidget.h>
24 #include <primitives/GTWidget.h>
25
26 #include <QRegularExpression>
27 #include <QStringBuilder>
28 #include <QTabWidget>
29
30 #include <U2Gui/HoverQLabel.h>
31
32 #include "GTUtilsDashboard.h"
33
34 namespace U2 {
35 using namespace HI;
36
37 const QString GTUtilsDashboard::TREE_ROOT_ID = ExternalToolsDashboardWidget::TREE_ID;
38
toString() const39 QString GTUtilsDashboard::Notification::toString() const {
40 return "[" % type.toUpper() % "][" % element % "] " % message;
41 }
42
43 #define GT_CLASS_NAME "GTUtilsDashboard"
44
45 #define GT_METHOD_NAME "getCopyButton"
getCopyButton(GUITestOpStatus & os,const QString & toolRunNodeId)46 QWidget *GTUtilsDashboard::getCopyButton(GUITestOpStatus &os, const QString &toolRunNodeId) {
47 auto node = getExternalToolNode(os, toolRunNodeId);
48 return GTWidget::findWidget(os, "copyButton", node);
49 }
50 #undef GT_METHOD_NAME
51
52 #define GT_METHOD_NAME "getExternalToolsWidget"
getExternalToolsWidget(GUITestOpStatus & os)53 ExternalToolsDashboardWidget *GTUtilsDashboard::getExternalToolsWidget(GUITestOpStatus &os) {
54 Dashboard *dashboard = getDashboard(os);
55 return GTWidget::findWidgetByType<ExternalToolsDashboardWidget *>(os, dashboard, "External tools widget is not found");
56 }
57 #undef GT_METHOD_NAME
58
59 #define GT_METHOD_NAME "getExternalToolNode"
getExternalToolNode(GUITestOpStatus & os,const QString & nodeId)60 ExternalToolsTreeNode *GTUtilsDashboard::getExternalToolNode(GUITestOpStatus &os, const QString &nodeId) {
61 ExternalToolsDashboardWidget *widget = getExternalToolsWidget(os);
62 ExternalToolsTreeNode *node = qobject_cast<ExternalToolsTreeNode *>(GTWidget::findWidget(os, nodeId, widget));
63 GT_CHECK_RESULT(node != nullptr, "External tool node not found: " + nodeId, nullptr);
64 return node;
65 }
66 #undef GT_METHOD_NAME
67
68 #define GT_METHOD_NAME "getExternalToolNodeByText"
getExternalToolNodeByText(GUITestOpStatus & os,const QString & textPattern,bool isExactMatch)69 ExternalToolsTreeNode *GTUtilsDashboard::getExternalToolNodeByText(GUITestOpStatus &os, const QString &textPattern, bool isExactMatch) {
70 return getExternalToolNodeByText(os, nullptr, textPattern, isExactMatch);
71 }
72 #undef GT_METHOD_NAME
73
74 #define GT_METHOD_NAME "getExternalToolNodesByText"
getExternalToolNodesByText(HI::GUITestOpStatus & os,ExternalToolsTreeNode * parent,const QString & textPattern,bool isExactMatch)75 QList<ExternalToolsTreeNode *> GTUtilsDashboard::getExternalToolNodesByText(HI::GUITestOpStatus &os, ExternalToolsTreeNode *parent, const QString &textPattern, bool isExactMatch) {
76 QList<ExternalToolsTreeNode *> nodes = parent == nullptr ? getExternalToolsWidget(os)->findChildren<ExternalToolsTreeNode *>() : parent->children;
77 QList<ExternalToolsTreeNode *> result;
78 for (auto node : qAsConst(nodes)) {
79 if (node->content == textPattern) {
80 result << node;
81 } else if (!isExactMatch && node->content.contains(textPattern)) {
82 result << node;
83 }
84 }
85 return result;
86 }
87 #undef GT_METHOD_NAME
88
89 #define GT_METHOD_NAME "getExternalToolNodeByTextWithParent"
getExternalToolNodeByText(GUITestOpStatus & os,ExternalToolsTreeNode * parent,const QString & textPattern,bool isExactMatch)90 ExternalToolsTreeNode *GTUtilsDashboard::getExternalToolNodeByText(GUITestOpStatus &os, ExternalToolsTreeNode *parent, const QString &textPattern, bool isExactMatch) {
91 QList<ExternalToolsTreeNode *> nodes = parent == nullptr ? getExternalToolsWidget(os)->findChildren<ExternalToolsTreeNode *>() : parent->children;
92 for (auto node : qAsConst(nodes)) {
93 if (node->content == textPattern) {
94 return node;
95 } else if (!isExactMatch && node->content.contains(textPattern)) {
96 return node;
97 }
98 }
99 GT_CHECK_RESULT(false, "External tool node by text not found: " + textPattern, nullptr);
100 }
101 #undef GT_METHOD_NAME
102
getTabWidget(HI::GUITestOpStatus & os)103 QTabWidget *GTUtilsDashboard::getTabWidget(HI::GUITestOpStatus &os) {
104 return GTWidget::findExactWidget<QTabWidget *>(os, "WorkflowTabView", GTUtilsMdi::activeWindow(os));
105 }
106
findLoadSchemaButton(HI::GUITestOpStatus & os)107 QToolButton *GTUtilsDashboard::findLoadSchemaButton(HI::GUITestOpStatus &os) {
108 Dashboard *dashboard = findDashboard(os);
109 return dashboard == nullptr ? nullptr : dashboard->findChild<QToolButton *>("loadSchemaButton");
110 }
111
getDashboardName(GUITestOpStatus & os,int dashboardNumber)112 const QString GTUtilsDashboard::getDashboardName(GUITestOpStatus &os, int dashboardNumber) {
113 return GTTabWidget::getTabName(os, getTabWidget(os), dashboardNumber);
114 }
115
getFileButtonLabels(QWidget * parentWidget)116 static QStringList getFileButtonLabels(QWidget *parentWidget) {
117 QList<QToolButton *> buttons = parentWidget->findChildren<QToolButton *>();
118 QStringList labels;
119 for (auto button : qAsConst(buttons)) {
120 labels << button->text();
121 }
122 return labels;
123 }
124
getInputFiles(HI::GUITestOpStatus & os)125 QStringList GTUtilsDashboard::getInputFiles(HI::GUITestOpStatus &os) {
126 openTab(os, Input);
127 auto dashboard = getDashboard(os);
128 auto parametersWidget = GTWidget::findWidget(os, "ParametersDashboardWidget", dashboard);
129 return getFileButtonLabels(parametersWidget);
130 }
131
getOutputFiles(HI::GUITestOpStatus & os)132 QStringList GTUtilsDashboard::getOutputFiles(HI::GUITestOpStatus &os) {
133 auto dashboard = getDashboard(os);
134 auto outputFilesWidget = GTWidget::findWidget(os, "OutputFilesDashboardWidget", dashboard);
135 return getFileButtonLabels(outputFilesWidget);
136 }
137
138 #define GT_METHOD_NAME "clickOutputFile"
clickOutputFile(GUITestOpStatus & os,const QString & outputFileName)139 void GTUtilsDashboard::clickOutputFile(GUITestOpStatus &os, const QString &outputFileName) {
140 auto dashboard = getDashboard(os);
141 auto outputFilesWidget = GTWidget::findWidget(os, "OutputFilesDashboardWidget", dashboard);
142 auto button = GTWidget::findButtonByText(os, outputFileName, outputFilesWidget);
143 GTWidget::click(os, button);
144 }
145 #undef GT_METHOD_NAME
146
hasNotifications(HI::GUITestOpStatus & os)147 bool GTUtilsDashboard::hasNotifications(HI::GUITestOpStatus &os) {
148 openTab(os, Overview);
149 auto dashboard = getDashboard(os);
150 auto notificationsWidget = GTWidget::findWidget(os, "NotificationsDashboardWidget", dashboard);
151 return notificationsWidget->isVisible();
152 }
153
154 #define GT_METHOD_NAME "getNotificationTypeFromHtml"
getNotificationTypeFromHtml(HI::GUITestOpStatus & os,const QString & html)155 QString GTUtilsDashboard::getNotificationTypeFromHtml(HI::GUITestOpStatus &os, const QString &html) {
156 QString type;
157
158 int start = html.indexOf("<img class=\"");
159 int end = html.indexOf("\"", start + 12); // 12 = length of "<img class=\""
160 GT_CHECK_RESULT(start >= 0 && end >= 0, "Dashboard notification type not found", type)
161
162 start += 12;
163 end -= start;
164 type = html.mid(start, end);
165 return type;
166 }
167 #undef GT_METHOD_NAME
168
169 #define GT_METHOD_NAME "getNotificationCellText"
getNotificationCellText(HI::GUITestOpStatus & os,const QGridLayout & tableLayout,const int row,const int col)170 QString GTUtilsDashboard::getNotificationCellText(HI::GUITestOpStatus &os, const QGridLayout &tableLayout, const int row, const int col) {
171 const QWidget *cellWidget = tableLayout.itemAtPosition(row, col)->widget();
172 QString text;
173
174 if (cellWidget != nullptr && cellWidget->objectName() == "tableCell") {
175 if (const QLayout *const cellLayout = cellWidget->layout()) {
176 for (int labelInd = 0; labelInd < cellLayout->count(); ++labelInd) {
177 if (const auto *const label = qobject_cast<QLabel *>(cellLayout->itemAt(labelInd)->widget())) {
178 text = label->text();
179 }
180 }
181 }
182 }
183 GT_CHECK_RESULT(!text.isEmpty(),
184 QString("Error getting (%1,%2) cell of dashboard notification table").arg(row).arg(col),
185 text)
186 return text;
187 }
188 #undef GT_METHOD_NAME
189
190 #define GT_METHOD_NAME "getNotifications"
getNotifications(GUITestOpStatus & os)191 QList<GTUtilsDashboard::Notification> GTUtilsDashboard::getNotifications(GUITestOpStatus &os) {
192 const QString notificationsWidgetName = "NotificationsDashboardWidget";
193 QWidget *const notificationsWidget = GTWidget::findWidget(os, notificationsWidgetName, GTUtilsDashboard::getDashboard(os));
194 const auto tableLayout = qobject_cast<QGridLayout *>(notificationsWidget->layout());
195 QList<Notification> notifications;
196
197 GT_CHECK_RESULT(tableLayout != nullptr && tableLayout->columnCount() == 3,
198 notificationsWidgetName % " was found, but cannot be used in a test",
199 notifications)
200
201 const int notificationsNumber = tableLayout->rowCount();
202 for (int row = 1; row < notificationsNumber; row++) {
203 const QString type = getNotificationTypeFromHtml(os, getNotificationCellText(os, *tableLayout, row, 0));
204 const QString element = getNotificationCellText(os, *tableLayout, row, 1);
205 const QString message = getNotificationCellText(os, *tableLayout, row, 2);
206 notifications << Notification {type, element, message};
207 }
208 return notifications;
209 }
210 #undef GT_METHOD_NAME
211
getJoinedNotificationsString(GUITestOpStatus & os)212 QString GTUtilsDashboard::getJoinedNotificationsString(GUITestOpStatus &os) {
213 const auto notifications = getNotifications(os);
214 QStringList stringNotifications;
215 for (const auto ¬ification : qAsConst(notifications)) {
216 stringNotifications << notification.toString();
217 }
218 return stringNotifications.join('\n');
219 }
220
getTabObjectName(Tabs tab)221 QString GTUtilsDashboard::getTabObjectName(Tabs tab) {
222 switch (tab) {
223 case Overview:
224 return "overviewTabButton";
225 case Input:
226 return "inputTabButton";
227 case ExternalTools:
228 return "externalToolsTabButton";
229 }
230 return "unknown tab";
231 }
232
233 #define GT_METHOD_NAME "findDashboard"
findDashboard(HI::GUITestOpStatus & os)234 Dashboard *GTUtilsDashboard::findDashboard(HI::GUITestOpStatus &os) {
235 QTabWidget *tabWidget = getTabWidget(os);
236 return tabWidget == nullptr ? nullptr : qobject_cast<Dashboard *>(tabWidget->currentWidget());
237 }
238 #undef GT_METHOD_NAME
239
240 #define GT_METHOD_NAME "getDashboard"
getDashboard(HI::GUITestOpStatus & os)241 Dashboard *GTUtilsDashboard::getDashboard(HI::GUITestOpStatus &os) {
242 auto dashboard = findDashboard(os);
243 GT_CHECK_RESULT(dashboard != nullptr, "Dashboard widget not found", nullptr);
244 return dashboard;
245 }
246 #undef GT_METHOD_NAME
247
248 #define GT_METHOD_NAME "openTab"
openTab(HI::GUITestOpStatus & os,Tabs tab)249 void GTUtilsDashboard::openTab(HI::GUITestOpStatus &os, Tabs tab) {
250 QWidget *dashboard = findDashboard(os);
251 GT_CHECK(dashboard != nullptr, "Dashboard widget not found");
252
253 QString tabButtonObjectName = getTabObjectName(tab);
254 QToolButton *tabButton = GTWidget::findExactWidget<QToolButton *>(os, tabButtonObjectName, dashboard);
255 GT_CHECK(tabButton != nullptr, "Tab button not found: " + tabButtonObjectName);
256
257 GTWidget::click(os, tabButton);
258 }
259 #undef GT_METHOD_NAME
260
261 #define GT_METHOD_NAME "hasTab"
hasTab(HI::GUITestOpStatus & os,Tabs tab)262 bool GTUtilsDashboard::hasTab(HI::GUITestOpStatus &os, Tabs tab) {
263 QWidget *dashboard = findDashboard(os);
264 GT_CHECK_RESULT(dashboard != nullptr, "Dashboard is not found", false);
265
266 QString tabButtonObjectName = getTabObjectName(tab);
267 QWidget *button = dashboard->findChild<QWidget *>(tabButtonObjectName);
268 return button != nullptr && button->isVisible();
269 }
270 #undef GT_METHOD_NAME
271
272 #define GT_METHOD_NAME "getNodeText"
getNodeText(GUITestOpStatus & os,const QString & nodeId)273 QString GTUtilsDashboard::getNodeText(GUITestOpStatus &os, const QString &nodeId) {
274 return getExternalToolNode(os, nodeId)->content;
275 }
276 #undef GT_METHOD_NAME
277
278 #define GT_METHOD_NAME "getChildrenNodesCount"
getChildrenNodesCount(GUITestOpStatus & os,const QString & nodeId)279 int GTUtilsDashboard::getChildrenNodesCount(GUITestOpStatus &os, const QString &nodeId) {
280 return nodeId == TREE_ROOT_ID ? getExternalToolsWidget(os)->getTopLevelNodes().size() : getExternalToolNode(os, nodeId)->children.count();
281 }
282 #undef GT_METHOD_NAME
283
284 #define GT_METHOD_NAME "getChildNodes"
getChildNodes(GUITestOpStatus & os,const QString & nodeId)285 QList<ExternalToolsTreeNode *> GTUtilsDashboard::getChildNodes(GUITestOpStatus &os, const QString &nodeId) {
286 return nodeId == TREE_ROOT_ID ? getExternalToolsWidget(os)->getTopLevelNodes() : getExternalToolNode(os, nodeId)->children;
287 }
288 #undef GT_METHOD_NAME
289
290 #define GT_METHOD_NAME "getChildNodeId"
getChildNodeId(GUITestOpStatus & os,const QString & nodeId,int childIndex)291 QString GTUtilsDashboard::getChildNodeId(GUITestOpStatus &os, const QString &nodeId, int childIndex) {
292 return getDescendantNodeId(os, nodeId, {childIndex});
293 }
294 #undef GT_METHOD_NAME
295
296 #define GT_METHOD_NAME "getDescendantNodeId"
getDescendantNodeId(GUITestOpStatus & os,const QString & nodeId,const QList<int> & childIndexes)297 QString GTUtilsDashboard::getDescendantNodeId(GUITestOpStatus &os, const QString &nodeId, const QList<int> &childIndexes) {
298 QList<ExternalToolsTreeNode *> childNodes = getChildNodes(os, nodeId);
299 QString resultNodeId = nodeId;
300 for (int i : qAsConst(childIndexes)) {
301 GT_CHECK_RESULT(i >= 0 && i < childNodes.size(), "Illegal child index: " + QString::number(i) + ", nodes: " + childNodes.size(), "");
302 resultNodeId = childNodes[i]->objectName();
303 childNodes = childNodes[i]->children;
304 }
305 return resultNodeId;
306 }
307 #undef GT_METHOD_NAME
308
309 #define GT_METHOD_NAME "getChildWithTextId"
getChildWithTextId(GUITestOpStatus & os,const QString & nodeId,const QString & text)310 QString GTUtilsDashboard::getChildWithTextId(GUITestOpStatus &os, const QString &nodeId, const QString &text) {
311 int childrenCount = getChildrenNodesCount(os, nodeId);
312 QString resultChildId;
313 QStringList quotedChildrenTexts;
314 for (int i = 0; i < childrenCount; i++) {
315 const QString currentChildId = getChildNodeId(os, nodeId, i);
316 const QString childText = getNodeText(os, currentChildId);
317 quotedChildrenTexts << "\'" + childText + "\'";
318 if (text == childText) {
319 GT_CHECK_RESULT(resultChildId.isEmpty(),
320 QString("Expected text '%1' is not unique among the node with ID '%2' children")
321 .arg(text)
322 .arg(nodeId),
323 "");
324 resultChildId = currentChildId;
325 }
326 }
327
328 GT_CHECK_RESULT(!resultChildId.isEmpty(),
329 QString("Child with text '%1' not found among the node with ID '%2' children; there are children with the following texts: %3")
330 .arg(text)
331 .arg(nodeId)
332 .arg(quotedChildrenTexts.join(", ")),
333 "");
334
335 return resultChildId;
336 }
337 #undef GT_METHOD_NAME
338
339 #define GT_METHOD_NAME "hasLimitationMessage"
hasLimitationMessage(GUITestOpStatus & os,const QString & nodeId)340 bool GTUtilsDashboard::hasLimitationMessage(GUITestOpStatus &os, const QString &nodeId) {
341 return !getLimitationMessage(os, nodeId).isEmpty();
342 }
343 #undef GT_METHOD_NAME
344
345 #define GT_METHOD_NAME "getLimitationMessage"
getLimitationMessage(GUITestOpStatus & os,const QString & nodeId)346 QString GTUtilsDashboard::getLimitationMessage(GUITestOpStatus &os, const QString &nodeId) {
347 return nodeId == TREE_ROOT_ID ? getExternalToolsWidget(os)->getLimitationWarningHtml() : getExternalToolNode(os, nodeId)->limitationWarningHtml;
348 }
349 #undef GT_METHOD_NAME
350
351 #define GT_METHOD_NAME "parseUrlFromContent"
parseUrlFromContent(GUITestOpStatus & os,const QString & content)352 static QString parseUrlFromContent(GUITestOpStatus &os, const QString &content) {
353 QString urlStartToken = "<a href=\"";
354 int urlStartTokenIdx = content.lastIndexOf(urlStartToken);
355 GT_CHECK_RESULT(urlStartTokenIdx > 0, "urlStartToken is not found, text: " + content, "");
356 int urlStartIdx = urlStartTokenIdx + urlStartToken.length();
357 int urlEndIdx = content.indexOf("\"", urlStartIdx + 1);
358 GT_CHECK_RESULT(urlEndIdx > 0, "urlEndToken is not found, text: " + content, "");
359 return content.mid(urlStartIdx, urlEndIdx - urlStartIdx);
360 }
361 #undef GT_METHOD_NAME
362
363 #define GT_METHOD_NAME "getLimitationMessageLogUrl"
getLogUrlFromNodeLimitationMessage(GUITestOpStatus & os,const QString & nodeId)364 QString GTUtilsDashboard::getLogUrlFromNodeLimitationMessage(GUITestOpStatus &os, const QString &nodeId) {
365 QString limitationMessage = getLimitationMessage(os, nodeId);
366 return parseUrlFromContent(os, limitationMessage);
367 }
368 #undef GT_METHOD_NAME
369
370 #define GT_METHOD_NAME "getLogUrlFromOutputContent"
getLogUrlFromOutputContent(GUITestOpStatus & os,const QString & outputNodeId)371 QString GTUtilsDashboard::getLogUrlFromOutputContent(GUITestOpStatus &os, const QString &outputNodeId) {
372 auto content = getExternalToolNode(os, outputNodeId)->content;
373 return parseUrlFromContent(os, content);
374 }
375 #undef GT_METHOD_NAME
376
377 #define GT_METHOD_NAME "getCopyButtonSize"
getCopyButtonSize(GUITestOpStatus & os,const QString & toolRunNodeId)378 QSize GTUtilsDashboard::getCopyButtonSize(GUITestOpStatus &os, const QString &toolRunNodeId) {
379 return getCopyButton(os, toolRunNodeId)->rect().size();
380 }
381 #undef GT_METHOD_NAME
382
383 #define GT_METHOD_NAME "clickCopyButton"
clickCopyButton(GUITestOpStatus & os,const QString & toolRunNodeId)384 void GTUtilsDashboard::clickCopyButton(GUITestOpStatus &os, const QString &toolRunNodeId) {
385 GTWidget::click(os, getCopyButton(os, toolRunNodeId));
386 }
387 #undef GT_METHOD_NAME
388
389 #define GT_METHOD_NAME "isNodeVisible"
isNodeVisible(GUITestOpStatus & os,const QString & nodeId)390 bool GTUtilsDashboard::isNodeVisible(GUITestOpStatus &os, const QString &nodeId) {
391 return getExternalToolNode(os, nodeId)->isVisible();
392 }
393 #undef GT_METHOD_NAME
394
395 #define GT_METHOD_NAME "isNodeCollapsed"
isNodeCollapsed(GUITestOpStatus & os,const QString & nodeId)396 bool GTUtilsDashboard::isNodeCollapsed(GUITestOpStatus &os, const QString &nodeId) {
397 return !getExternalToolNode(os, nodeId)->isExpanded();
398 }
399 #undef GT_METHOD_NAME
400
401 #define GT_METHOD_NAME "collapseNode"
collapseNode(GUITestOpStatus & os,const QString & nodeId)402 void GTUtilsDashboard::collapseNode(GUITestOpStatus &os, const QString &nodeId) {
403 GT_CHECK(isNodeVisible(os, nodeId), QString("Node with ID '%1' is not visible. Some of the parent nodes are collapsed?").arg(nodeId));
404 GT_CHECK(!isNodeCollapsed(os, nodeId), QString("Node with ID '%1' is already collapsed.").arg(nodeId));
405 clickNodeTitle(os, getExternalToolNode(os, nodeId));
406 GT_CHECK(isNodeCollapsed(os, nodeId), QString("Node with ID '%1' was not collapsed.").arg(nodeId));
407 }
408 #undef GT_METHOD_NAME
409
410 #define GT_METHOD_NAME "expandNode"
expandNode(GUITestOpStatus & os,const QString & nodeId)411 void GTUtilsDashboard::expandNode(GUITestOpStatus &os, const QString &nodeId) {
412 GT_CHECK(isNodeVisible(os, nodeId), QString("Node with ID '%1' is not visible. Some of the parent nodes are collapsed?").arg(nodeId));
413 GT_CHECK(isNodeCollapsed(os, nodeId), QString("Node with ID '%1' is already expanded.").arg(nodeId));
414 clickNodeTitle(os, getExternalToolNode(os, nodeId));
415 GT_CHECK(!isNodeCollapsed(os, nodeId), QString("Node with ID '%1' was not expanded.").arg(nodeId));
416 }
417 #undef GT_METHOD_NAME
418
419 #define GT_METHOD_NAME "clickNodeTitle"
clickNodeTitle(GUITestOpStatus & os,ExternalToolsTreeNode * node)420 void GTUtilsDashboard::clickNodeTitle(GUITestOpStatus &os, ExternalToolsTreeNode *node) {
421 GT_CHECK(node != nullptr, "Node is null!");
422 GT_CHECK(node->badgeLabel->titleLabel != nullptr, "Node title label is null!");
423 GTWidget::click(os, node->badgeLabel->titleLabel);
424 }
425 #undef GT_METHOD_NAME
426
427 #undef GT_CLASS_NAME
428
429 } // namespace U2
430