📄 tst_qwebpage.cpp
字号:
/* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.*/#include <QtTest/QtTest>#include <qwebpage.h>#include <qwidget.h>#include <qwebview.h>#include <qwebframe.h>#include <qwebhistory.h>#include <qnetworkrequest.h>#include <QDebug>#include <QLineEdit>#include <QMenu>#include <qwebsecurityorigin.h>#include <qwebdatabase.h>#include <QPushButton>// Will try to wait for the condition while allowing event processing#define QTRY_COMPARE(__expr, __expected) \ do { \ const int __step = 50; \ const int __timeout = 5000; \ if ((__expr) != (__expected)) { \ QTest::qWait(0); \ } \ for (int __i = 0; __i < __timeout && ((__expr) != (__expected)); __i+=__step) { \ QTest::qWait(__step); \ } \ QCOMPARE(__expr, __expected); \ } while(0)//TESTED_CLASS=//TESTED_FILES=// Task 160192/** * Starts an event loop that runs until the given signal is received. Optionally the event loop * can return earlier on a timeout. * * \return \p true if the requested signal was received * \p false on timeout */static bool waitForSignal(QObject* obj, const char* signal, int timeout = 0){ QEventLoop loop; QObject::connect(obj, signal, &loop, SLOT(quit())); QTimer timer; QSignalSpy timeoutSpy(&timer, SIGNAL(timeout())); if (timeout > 0) { QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); timer.setSingleShot(true); timer.start(timeout); } loop.exec(); return timeoutSpy.isEmpty();}class tst_QWebPage : public QObject{ Q_OBJECTpublic: tst_QWebPage(); virtual ~tst_QWebPage();public slots: void init(); void cleanup(); void cleanupFiles();private slots: void initTestCase(); void cleanupTestCase(); void acceptNavigationRequest(); void loadFinished(); void acceptNavigationRequestWithNewWindow(); void userStyleSheet(); void modified(); void contextMenuCrash(); void database(); void createPlugin(); void destroyPlugin(); void createViewlessPlugin(); void multiplePageGroupsAndLocalStorage(); void cursorMovements(); void textSelection(); void textEditing();private:private: QWebView* m_view; QWebPage* m_page;};tst_QWebPage::tst_QWebPage(){}tst_QWebPage::~tst_QWebPage(){}void tst_QWebPage::init(){ m_view = new QWebView(); m_page = m_view->page();}void tst_QWebPage::cleanup(){ delete m_view;}void tst_QWebPage::cleanupFiles(){ QFile::remove("Databases.db"); QDir::current().rmdir("http_www.myexample.com_0"); QFile::remove("http_www.myexample.com_0.localstorage");}void tst_QWebPage::initTestCase(){ cleanupFiles(); // In case there are old files from previous runs}void tst_QWebPage::cleanupTestCase(){ cleanupFiles(); // Be nice}class NavigationRequestOverride : public QWebPage{public: NavigationRequestOverride(QWebView* parent, bool initialValue) : QWebPage(parent), m_acceptNavigationRequest(initialValue) {} bool m_acceptNavigationRequest;protected: virtual bool acceptNavigationRequest(QWebFrame* frame, const QNetworkRequest &request, QWebPage::NavigationType type) { Q_UNUSED(frame); Q_UNUSED(request); Q_UNUSED(type); return m_acceptNavigationRequest; }};void tst_QWebPage::acceptNavigationRequest(){ QSignalSpy loadSpy(m_view, SIGNAL(loadFinished(bool))); NavigationRequestOverride* newPage = new NavigationRequestOverride(m_view, false); m_view->setPage(newPage); m_view->setHtml(QString("<html><body><form name='tstform' action='data:text/html,foo'method='get'>" "<input type='text'><input type='submit'></form></body></html>"), QUrl()); QTRY_COMPARE(loadSpy.count(), 1); m_view->page()->mainFrame()->evaluateJavaScript("tstform.submit();"); newPage->m_acceptNavigationRequest = true; m_view->page()->mainFrame()->evaluateJavaScript("tstform.submit();"); QTRY_COMPARE(loadSpy.count(), 2); QCOMPARE(m_view->page()->mainFrame()->toPlainText(), QString("foo?")); // Restore default page m_view->setPage(0);}void tst_QWebPage::loadFinished(){ QSignalSpy spyLoadStarted(m_view, SIGNAL(loadStarted())); QSignalSpy spyLoadFinished(m_view, SIGNAL(loadFinished(bool))); m_view->setHtml(QString("data:text/html,<frameset cols=\"25%,75%\"><frame src=\"data:text/html," "<head><meta http-equiv='refresh' content='1'></head>foo \">" "<frame src=\"data:text/html,bar\"></frameset>"), QUrl()); QTRY_COMPARE(spyLoadFinished.count(), 1); QTest::qWait(3000); QVERIFY(spyLoadStarted.count() > 1); QVERIFY(spyLoadFinished.count() > 1); spyLoadFinished.clear(); m_view->setHtml(QString("data:text/html,<frameset cols=\"25%,75%\"><frame src=\"data:text/html," "foo \"><frame src=\"data:text/html,bar\"></frameset>"), QUrl()); QTRY_COMPARE(spyLoadFinished.count(), 1); QCOMPARE(spyLoadFinished.count(), 1);}class TestPage : public QWebPage{public: TestPage(QObject* parent = 0) : QWebPage(parent) {} struct Navigation { QPointer<QWebFrame> frame; QNetworkRequest request; NavigationType type; }; QList<Navigation> navigations; QList<QWebPage*> createdWindows; virtual bool acceptNavigationRequest(QWebFrame* frame, const QNetworkRequest &request, NavigationType type) { Navigation n; n.frame = frame; n.request = request; n.type = type; navigations.append(n); return true; } virtual QWebPage* createWindow(WebWindowType) { QWebPage* page = new TestPage(this); createdWindows.append(page); return page; }};void tst_QWebPage::acceptNavigationRequestWithNewWindow(){ TestPage* page = new TestPage(m_view); page->settings()->setAttribute(QWebSettings::LinksIncludedInFocusChain, true); m_page = page; m_view->setPage(m_page); m_view->setUrl(QString("data:text/html,<a href=\"data:text/html,Reached\" target=\"_blank\">Click me</a>")); QVERIFY(::waitForSignal(m_view, SIGNAL(loadFinished(bool)))); QFocusEvent fe(QEvent::FocusIn); m_page->event(&fe); QVERIFY(m_page->focusNextPrevChild(/*next*/ true)); QKeyEvent keyEnter(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier); m_page->event(&keyEnter); QCOMPARE(page->navigations.count(), 2); TestPage::Navigation n = page->navigations.at(1); QVERIFY(n.frame.isNull()); QCOMPARE(n.request.url().toString(), QString("data:text/html,Reached")); QVERIFY(n.type == QWebPage::NavigationTypeLinkClicked); QCOMPARE(page->createdWindows.count(), 1);}class TestNetworkManager : public QNetworkAccessManager{public: TestNetworkManager(QObject* parent) : QNetworkAccessManager(parent) {} QList<QUrl> requestedUrls;protected: virtual QNetworkReply* createRequest(Operation op, const QNetworkRequest &request, QIODevice* outgoingData) { requestedUrls.append(request.url()); return QNetworkAccessManager::createRequest(op, request, outgoingData); }};void tst_QWebPage::userStyleSheet(){ TestNetworkManager* networkManager = new TestNetworkManager(m_page); m_page->setNetworkAccessManager(networkManager); networkManager->requestedUrls.clear(); m_page->settings()->setUserStyleSheetUrl(QUrl("data:text/css,p { background-image: url('http://does.not/exist.png');}")); m_view->setHtml("<p>hello world</p>"); QVERIFY(::waitForSignal(m_view, SIGNAL(loadFinished(bool)))); QVERIFY(networkManager->requestedUrls.count() >= 2); QCOMPARE(networkManager->requestedUrls.at(0), QUrl("data:text/css,p { background-image: url('http://does.not/exist.png');}")); QCOMPARE(networkManager->requestedUrls.at(1), QUrl("http://does.not/exist.png"));}void tst_QWebPage::modified(){ m_page->mainFrame()->setUrl(QUrl("data:text/html,<body>blub")); QVERIFY(::waitForSignal(m_view, SIGNAL(loadFinished(bool)))); m_page->mainFrame()->setUrl(QUrl("data:text/html,<body id=foo contenteditable>blah")); QVERIFY(::waitForSignal(m_view, SIGNAL(loadFinished(bool)))); QVERIFY(!m_page->isModified());// m_page->mainFrame()->evaluateJavaScript("alert(document.getElementById('foo'))"); m_page->mainFrame()->evaluateJavaScript("document.getElementById('foo').focus()"); m_page->mainFrame()->evaluateJavaScript("document.execCommand('InsertText', true, 'Test');"); QVERIFY(m_page->isModified()); m_page->mainFrame()->evaluateJavaScript("document.execCommand('Undo', true);"); QVERIFY(!m_page->isModified()); m_page->mainFrame()->evaluateJavaScript("document.execCommand('Redo', true);"); QVERIFY(m_page->isModified()); QVERIFY(m_page->history()->canGoBack()); QVERIFY(!m_page->history()->canGoForward()); QCOMPARE(m_page->history()->count(), 2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -