1 /*
2 SPDX-FileCopyrightText: 2016 The Qt Company Ltd. <https://www.qt.io/licensing/>
3
4 This file is part of the QtWebEngine module of the Qt Toolkit.
5 SPDX-License-Identifier: GPL-3.0-only WITH Qt-GPL-exception-1.0 OR LicenseRef-Qt-Commercial
6 */
7 #ifndef WEBENGINE_TESTUTILS_H
8 #define WEBENGINE_TESTUTILS_H
9
10 #include <QEventLoop>
11 #include <QTimer>
12 #include <QWebEnginePage>
13
14 template<typename T, typename R>
15 struct RefWrapper {
16 R &ref;
operatorRefWrapper17 void operator()(const T& result) {
18 ref(result);
19 }
20 };
21
22 template<typename T>
23 class CallbackSpy {
24 public:
CallbackSpy()25 CallbackSpy() : called(false) {
26 timeoutTimer.setSingleShot(true);
27 QObject::connect(&timeoutTimer, SIGNAL(timeout()), &eventLoop, SLOT(quit()));
28 }
29
waitForResult()30 T waitForResult() {
31 if (!called) {
32 timeoutTimer.start(10000);
33 eventLoop.exec();
34 }
35 return result;
36 }
37
wasCalled()38 bool wasCalled() const {
39 return called;
40 }
41
operator()42 void operator()(const T &result) {
43 this->result = result;
44 called = true;
45 eventLoop.quit();
46 }
47
48 // Cheap rip-off of boost/std::ref
ref()49 RefWrapper<T, CallbackSpy<T> > ref()
50 {
51 RefWrapper<T, CallbackSpy<T> > wrapper = {*this};
52 return wrapper;
53 }
54
55 private:
56 Q_DISABLE_COPY(CallbackSpy)
57 bool called;
58 QTimer timeoutTimer;
59 QEventLoop eventLoop;
60 T result;
61 };
62
63 // taken from the qwebengine unittests
evaluateJavaScriptSync(QWebEnginePage * page,const QString & script)64 static inline QVariant evaluateJavaScriptSync(QWebEnginePage *page, const QString &script)
65 {
66 CallbackSpy<QVariant> spy;
67 page->runJavaScript(script, spy.ref());
68 return spy.waitForResult();
69 }
70
71 // Taken from QtWebEngine's tst_qwebenginepage.cpp
elementCenter(QWebEnginePage * page,const QString & id)72 static QPoint elementCenter(QWebEnginePage *page, const QString &id)
73 {
74 QVariantList rectList = evaluateJavaScriptSync(page,
75 "(function(){"
76 "var elem = document.getElementById('" + id + "');"
77 "var rect = elem.getBoundingClientRect();"
78 "return [rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top];"
79 "})()").toList();
80
81 if (rectList.count() != 4) {
82 qWarning("elementCenter failed.");
83 return QPoint();
84 }
85 const QRect rect(rectList.at(0).toInt(), rectList.at(1).toInt(),
86 rectList.at(2).toInt(), rectList.at(3).toInt());
87 return rect.center();
88 }
89 #endif
90