#include <QtTest/QtTest>
#include <qwebpage.h>
#include <qwebelement.h>
#include <qwebview.h>
#include <qwebframe.h>
#include <qwebhistory.h>
#include <QAbstractItemView>
#include <QApplication>
#include <QComboBox>
#include <QPaintEngine>
#include <QPicture>
#include <QRegExp>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QTextCodec>
#ifndef QT_NO_OPENSSL
#include <qsslerror.h>
#endif
#include "../util.h"
class tst_QWebFrame : public QObject
{
Q_OBJECT
public:
bool eventFilter(QObject* watched, QEvent* event);
public Q_SLOTS:
void init();
void cleanup();
private Q_SLOTS:
void horizontalScrollAfterBack();
void symmetricUrl();
void progressSignal();
void urlChange();
void requestedUrl();
void requestedUrlAfterSetAndLoadFailures();
void javaScriptWindowObjectCleared_data();
void javaScriptWindowObjectCleared();
void javaScriptWindowObjectClearedOnEvaluate();
void setHtml();
void setHtmlWithImageResource();
void setHtmlWithStylesheetResource();
void setHtmlWithBaseURL();
void setHtmlWithJSAlert();
void ipv6HostEncoding();
void metaData();
#if !defined(QT_NO_COMBOBOX)
void popupFocus();
#endif
void inputFieldFocus();
void hitTestContent();
void baseUrl_data();
void baseUrl();
void hasSetFocus();
void renderGeometry();
void renderHints();
void scrollPosition();
void scrollToAnchor();
void scrollbarsOff();
void evaluateWillCauseRepaint();
void setContent_data();
void setContent();
void setCacheLoadControlAttribute();
void setUrlWithPendingLoads();
void setUrlWithFragment_data();
void setUrlWithFragment();
void setUrlToEmpty();
void setUrlToInvalid();
void setUrlHistory();
void setUrlUsingStateObject();
void setUrlSameUrl();
void setUrlThenLoads_data();
void setUrlThenLoads();
void loadFinishedAfterNotFoundError();
void loadInSignalHandlers_data();
void loadInSignalHandlers();
private:
QWebView* m_view;
QWebPage* m_page;
QWebView* m_inputFieldsTestView;
int m_inputFieldTestPaintCount;
};
bool tst_QWebFrame::eventFilter(QObject* watched, QEvent* event)
{
if (watched == m_inputFieldsTestView) {
if (event->type() == QEvent::Paint)
m_inputFieldTestPaintCount++;
}
return QObject::eventFilter(watched, event);
}
void tst_QWebFrame::init()
{
m_view = new QWebView();
m_page = m_view->page();
}
void tst_QWebFrame::cleanup()
{
delete m_view;
}
void tst_QWebFrame::symmetricUrl()
{
QVERIFY(m_view->url().isEmpty());
QCOMPARE(m_view->history()->count(), 0);
QUrl dataUrl("data:text/html,<h1>Test");
m_view->setUrl(dataUrl);
QCOMPARE(m_view->url(), dataUrl);
QCOMPARE(m_view->history()->count(), 0);
QVERIFY(m_view->page()->mainFrame()->toPlainText().isEmpty());
::waitForSignal(m_view, SIGNAL(loadFinished(bool)));
QCOMPARE(m_view->history()->count(), 1);
QCOMPARE(m_view->page()->mainFrame()->toPlainText(), QString("Test"));
QUrl dataUrl2("data:text/html,<h1>Test2");
QUrl dataUrl3("data:text/html,<h1>Test3");
m_view->setUrl(dataUrl2);
m_view->setUrl(dataUrl3);
QCOMPARE(m_view->url(), dataUrl3);
::waitForSignal(m_view, SIGNAL(loadFinished(bool)));
QCOMPARE(m_view->history()->count(), 2);
QCOMPARE(m_view->page()->mainFrame()->toPlainText(), QString("Test3"));
}
void tst_QWebFrame::progressSignal()
{
QSignalSpy progressSpy(m_view, SIGNAL(loadProgress(int)));
QUrl dataUrl("data:text/html,<h1>Test");
m_view->setUrl(dataUrl);
::waitForSignal(m_view, SIGNAL(loadFinished(bool)));
QVERIFY(progressSpy.size() >= 2);
QCOMPARE(progressSpy.first().first().toInt(), 10);
QCOMPARE(progressSpy.last().first().toInt(), 100);
}
void tst_QWebFrame::urlChange()
{
QSignalSpy urlSpy(m_page->mainFrame(), SIGNAL(urlChanged(QUrl)));
QUrl dataUrl("data:text/html,<h1>Test");
m_view->setUrl(dataUrl);
::waitForSignal(m_page->mainFrame(), SIGNAL(urlChanged(QUrl)));
QCOMPARE(urlSpy.size(), 1);
QUrl dataUrl2("data:text/html,<html><head><title>title</title></head><body><h1>Test</body></html>");
m_view->setUrl(dataUrl2);
::waitForSignal(m_page->mainFrame(), SIGNAL(urlChanged(QUrl)));
QCOMPARE(urlSpy.size(), 2);
}
class FakeReply : public QNetworkReply {
Q_OBJECT
public:
static const QUrl urlFor404ErrorWithoutContents;
FakeReply(const QNetworkRequest& request, QObject* parent = 0)
: QNetworkReply(parent)
{
setOperation(QNetworkAccessManager::GetOperation);
setRequest(request);
setUrl(request.url());
if (request.url() == QUrl("qrc:/test1.html")) {
setHeader(QNetworkRequest::LocationHeader, QString("qrc:/test2.html"));
setAttribute(QNetworkRequest::RedirectionTargetAttribute, QUrl("qrc:/test2.html"));
QTimer::singleShot(0, this, SLOT(continueRedirect()));
}
#ifndef QT_NO_OPENSSL
else if (request.url() == QUrl("qrc:/fake-ssl-error.html")) {
setError(QNetworkReply::SslHandshakeFailedError, tr("Fake error!"));
QTimer::singleShot(0, this, SLOT(continueError()));
}
#endif
else if (request.url().host() == QLatin1String("abcdef.abcdef")) {
setError(QNetworkReply::HostNotFoundError, tr("Invalid URL"));
QTimer::singleShot(0, this, SLOT(continueError()));
} else if (request.url() == FakeReply::urlFor404ErrorWithoutContents) {
setError(QNetworkReply::ContentNotFoundError, "Not found");
setAttribute(QNetworkRequest::HttpStatusCodeAttribute, 404);
QTimer::singleShot(0, this, SLOT(continueError()));
}
open(QIODevice::ReadOnly);
}
~FakeReply()
{
close();
}
virtual void abort() {}
virtual void close() {}
protected:
qint64 readData(char*, qint64)
{
return 0;
}
private Q_SLOTS:
void continueRedirect()
{
emit metaDataChanged();
emit finished();
}
void continueError()
{
emit error(this->error());
emit finished();
}
};
const QUrl FakeReply::urlFor404ErrorWithoutContents = QUrl("http://this.will/return-http-404-error-without-contents.html");
class FakeNetworkManager : public QNetworkAccessManager {
Q_OBJECT
public:
FakeNetworkManager(QObject* parent) : QNetworkAccessManager(parent) { }
protected:
virtual QNetworkReply* createRequest(Operation op, const QNetworkRequest& request, QIODevice* outgoingData)
{
QString url = request.url().toString();
if (op == QNetworkAccessManager::GetOperation) {
#ifndef QT_NO_OPENSSL
if (url == "qrc:/fake-ssl-error.html") {
FakeReply* reply = new FakeReply(request, this);
QList<QSslError> errors;
emit sslErrors(reply, errors << QSslError(QSslError::UnspecifiedError));
return reply;
}
#endif
if (url == "qrc:/test1.html" || url == "http://abcdef.abcdef/" || request.url() == FakeReply::urlFor404ErrorWithoutContents)
return new FakeReply(request, this);
}
return QNetworkAccessManager::createRequest(op, request, outgoingData);
}
};
void tst_QWebFrame::requestedUrl()
{
QWebPage page;
QWebFrame* frame = page.mainFrame();
QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
FakeNetworkManager* networkManager = new FakeNetworkManager(&page);
page.setNetworkAccessManager(networkManager);
frame->setUrl(QUrl("qrc:/test1.html"));
waitForSignal(frame, SIGNAL(loadFinished(bool)), 200);
QCOMPARE(spy.count(), 1);
QCOMPARE(frame->requestedUrl(), QUrl("qrc:/test1.html"));
QCOMPARE(frame->url(), QUrl("qrc:/test2.html"));
frame->setUrl(QUrl("qrc:/non-existent.html"));
waitForSignal(frame, SIGNAL(loadFinished(bool)), 200);
QCOMPARE(spy.count(), 2);
QCOMPARE(frame->requestedUrl(), QUrl("qrc:/non-existent.html"));
QCOMPARE(frame->url(), QUrl("qrc:/non-existent.html"));
frame->setUrl(QUrl("http://abcdef.abcdef"));
waitForSignal(frame, SIGNAL(loadFinished(bool)), 200);
QCOMPARE(spy.count(), 3);
QCOMPARE(frame->requestedUrl(), QUrl("http://abcdef.abcdef/"));
QCOMPARE(frame->url(), QUrl("http://abcdef.abcdef/"));
#ifndef QT_NO_OPENSSL
qRegisterMetaType<QList<QSslError> >("QList<QSslError>");
qRegisterMetaType<QNetworkReply* >("QNetworkReply*");
QSignalSpy spy2(page.networkAccessManager(), SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)));
frame->setUrl(QUrl("qrc:/fake-ssl-error.html"));
waitForSignal(frame, SIGNAL(loadFinished(bool)), 200);
QCOMPARE(spy2.count(), 1);
QCOMPARE(frame->requestedUrl(), QUrl("qrc:/fake-ssl-error.html"));
QCOMPARE(frame->url(), QUrl("qrc:/fake-ssl-error.html"));
#endif
}
void tst_QWebFrame::requestedUrlAfterSetAndLoadFailures()
{
QWebPage page;
QWebFrame* frame = page.mainFrame();
QSignalSpy spy(frame, SIGNAL(loadFinished(bool)));
const QUrl first("http://abcdef.abcdef/");
frame->setUrl(first);
::waitForSignal(frame, SIGNAL(loadFinished(bool)));
QCOMPARE(frame->url(), first);
QCOMPARE(frame->requestedUrl(), first);
QVERIFY(!spy.at(0).first().toBool());
const QUrl second("http://abcdef.abcdef/another_page.html");
QVERIFY(first != second);
frame->load(second);
::waitForSignal(frame, SIGNAL(loadFinished(bool)));
QCOMPARE(frame->url(), first);
QCOMPARE(frame->requestedUrl(), second);
QVERIFY(!spy.at(1).first().toBool());
}
void tst_QWebFrame::javaScriptWindowObjectCleared_data()
{
QTest::addColumn<QString>("html");
QTest::addColumn<int>("signalCount");
QTest::newRow("with <script>") << "<html><body><script>i=0</script><p>hello world</p></body></html>" << 1;
QTest::newRow("with empty <script>") << "<html><body><script></script><p>hello world</p></body></html>" << 0;
QTest::newRow("without <script>") << "<html><body><p>hello world</p></body></html>" << 0;
}
void tst_QWebFrame::javaScriptWindowObjectCleared()
{
QWebPage page;
QWebFrame* frame = page.mainFrame();
QSignalSpy spy(frame, SIGNAL(javaScriptWindowObjectCleared()));
QFETCH(QString, html);
frame->setHtml(html);
QFETCH(int, signalCount);
QCOMPARE(spy.count(), signalCount);
}
void tst_QWebFrame::javaScriptWindowObjectClearedOnEvaluate()
{
QWebPage page;
QWebFrame* frame = page.mainFrame();
QSignalSpy spy(frame, SIGNAL(javaScriptWindowObjectCleared()));
frame->setHtml("<html></html>");
QCOMPARE(spy.count(), 0);
frame->evaluateJavaScript("var a = 'a';");
QCOMPARE(spy.count(), 1);
frame->evaluateJavaScript("var a = 1;");
QCOMPARE(spy.count(), 1);
}
void tst_QWebFrame::setHtml()
{
QString html("<html><head></head><body><p>hello world</p></body></html>");
QSignalSpy spy(m_view->page(), SIGNAL(loadFinished(bool)));
m_view->page()->mainFrame()->setHtml(html);
QCOMPARE(m_view->page()->mainFrame()->toHtml(), html);
QCOMPARE(spy.count(), 1);
}
void tst_QWebFrame::setHtmlWithImageResource()
{
QLatin1String html("<html><body><p>hello world</p><img src='qrc:/image.png'/></body></html>");
QWebPage page;
QWebFrame* frame = page.mainFrame();
frame->setHtml(html, QUrl(QLatin1String("file:///path/to/file")));
waitForSignal(frame, SIGNAL(loadFinished(bool)), 200);
QCOMPARE(frame->evaluateJavaScript("document.images.length").toInt(), 1);
QCOMPARE(frame->evaluateJavaScript("document.images[0].width").toInt(), 128);
QCOMPARE(frame->evaluateJavaScript("document.images[0].height").toInt(), 128);
frame->setHtml(html);
waitForSignal(frame, SIGNAL(loadFinished(bool)), 200);
QCOMPARE(frame->evaluateJavaScript("document.images.length").toInt(), 1);
QCOMPARE(frame->evaluateJavaScript("document.images[0].width").toInt(), 0);
QCOMPARE(frame->evaluateJavaScript("document.images[0].height").toInt(), 0);
}
void tst_QWebFrame::setHtmlWithStylesheetResource()
{
const char* htmlData =
"<html>"
"<head>"
"<link rel='stylesheet' href='qrc:/style.css' type='text/css' />"
"</head>"
"<body>"
"<p id='idP'>some text</p>"
"</body>"
"</html>";
QLatin1String html(htmlData);
QWebPage page;
QWebFrame* frame = page.mainFrame();
QWebElement webElement;
frame->setHtml(html, QUrl(QLatin1String("qrc:///file")));
waitForSignal(frame, SIGNAL(loadFinished(bool)), 200);
webElement = frame->documentElement().findFirst("p");
QCOMPARE(webElement.styleProperty("color", QWebElement::CascadedStyle), QLatin1String("red"));
frame->setHtml(html, QUrl(QLatin1String("http://www.example.com/")));
waitForSignal(frame, SIGNAL(loadFinished(bool)), 200);
webElement = frame->documentElement().findFirst("p");
QCOMPARE(webElement.styleProperty("color", QWebElement::CascadedStyle), QString());
}
void tst_QWebFrame::setHtmlWithBaseURL()
{
if (!QDir(TESTS_SOURCE_DIR).exists())
W_QSKIP(QString("This test requires access to resources found in '%1'").arg(TESTS_SOURCE_DIR).toLatin1().constData(), SkipAll);
QDir::setCurrent(TESTS_SOURCE_DIR);
QString html("<html><body><p>hello world</p><img src='resources/image2.png'/></body></html>");
QWebPage page;
QWebFrame* frame = page.mainFrame();
QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
frame->setHtml(html, QUrl::fromLocalFile(TESTS_SOURCE_DIR));
waitForSignal(frame, SIGNAL(loadFinished(bool)), 200);
QCOMPARE(spy.count(), 1);
QCOMPARE(frame->evaluateJavaScript("document.images.length").toInt(), 1);
QCOMPARE(frame->evaluateJavaScript("document.images[0].width").toInt(), 128);
QCOMPARE(frame->evaluateJavaScript("document.images[0].height").toInt(), 128);
QCOMPARE(m_view->page()->history()->count(), 0);
}
class MyPage : public QWebPage
{
public:
MyPage() : QWebPage(), alerts(0) {}
int alerts;
protected:
virtual void javaScriptAlert(QWebFrame*, const QString& msg)
{
alerts++;
QCOMPARE(msg, QString("foo"));
QTest::qWait(1000);
}
};
void tst_QWebFrame::setHtmlWithJSAlert()
{
QString html("<html><head></head><body><script>alert('foo');</script><p>hello world</p></body></html>");
MyPage page;
m_view->setPage(&page);
page.mainFrame()->setHtml(html);
QCOMPARE(page.alerts, 1);
QCOMPARE(m_view->page()->mainFrame()->toHtml(), html);
}
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());
QNetworkRequest redirectedRequest = request;
redirectedRequest.setUrl(QUrl("data:text/html,<p>hello"));
return QNetworkAccessManager::createRequest(op, redirectedRequest, outgoingData);
}
};
void tst_QWebFrame::ipv6HostEncoding()
{
TestNetworkManager* networkManager = new TestNetworkManager(m_page);
m_page->setNetworkAccessManager(networkManager);
networkManager->requestedUrls.clear();
QUrl baseUrl = QUrl::fromEncoded("http://[::1]/index.html");
m_view->setHtml("<p>Hi", baseUrl);
m_view->page()->mainFrame()->evaluateJavaScript("var r = new XMLHttpRequest();"
"r.open('GET', 'http://[::1]/test.xml', false);"
"r.send(null);"
);
QCOMPARE(networkManager->requestedUrls.count(), 1);
QCOMPARE(networkManager->requestedUrls.at(0), QUrl::fromEncoded("http://[::1]/test.xml"));
}
void tst_QWebFrame::metaData()
{
m_view->setHtml("<html>"
" <head>"
" <meta name=\"description\" content=\"Test description\">"
" <meta name=\"keywords\" content=\"HTML, JavaScript, Css\">"
" </head>"
"</html>");
QMultiMap<QString, QString> metaData = m_view->page()->mainFrame()->metaData();
QCOMPARE(metaData.count(), 2);
QCOMPARE(metaData.value("description"), QString("Test description"));
QCOMPARE(metaData.value("keywords"), QString("HTML, JavaScript, Css"));
QCOMPARE(metaData.value("nonexistant"), QString());
m_view->setHtml("<html>"
" <head>"
" <meta name=\"samekey\" content=\"FirstValue\">"
" <meta name=\"samekey\" content=\"SecondValue\">"
" </head>"
"</html>");
metaData = m_view->page()->mainFrame()->metaData();
QCOMPARE(metaData.count(), 2);
QStringList values = metaData.values("samekey");
QCOMPARE(values.count(), 2);
QVERIFY(values.contains("FirstValue"));
QVERIFY(values.contains("SecondValue"));
QCOMPARE(metaData.value("nonexistant"), QString());
}
#if !defined(QT_NO_COMBOBOX)
void tst_QWebFrame::popupFocus()
{
QWebView view;
view.setHtml("<html>"
" <body>"
" <select name=\"select\">"
" <option>1</option>"
" <option>2</option>"
" </select>"
" <input type=\"text\"> </input>"
" <textarea name=\"text_area\" rows=\"3\" cols=\"40\">"
"This test checks whether showing and hiding a popup"
"takes the focus away from the webpage."
" </textarea>"
" </body>"
"</html>");
view.resize(400, 100);
view.setFocus();
view.show();
QTest::qWaitForWindowExposed(&view);
view.activateWindow();
QTRY_VERIFY(view.hasFocus());
const QWebElement webCombo = view.page()->mainFrame()->documentElement().findFirst(QLatin1String("select[name=select]"));
QTest::mouseClick(&view, Qt::LeftButton, 0, webCombo.geometry().center());
QComboBox* combo = view.findChild<QComboBox*>();
QVERIFY(combo != 0);
QTRY_VERIFY(!view.hasFocus() && combo->view()->hasFocus());
combo->hidePopup();
QTRY_VERIFY(view.hasFocus()); }
#endif
void tst_QWebFrame::inputFieldFocus()
{
QWebView view;
view.setHtml("<html><body><input type=\"text\"></input></body></html>");
view.resize(400, 100);
view.show();
QTest::qWaitForWindowExposed(&view);
view.activateWindow();
view.setFocus();
QTRY_VERIFY(view.hasFocus());
int delay = qApp->cursorFlashTime() * 2;
bool autoSipEnabled = qApp->autoSipEnabled();
qApp->setAutoSipEnabled(false);
const QWebElement inputElement = view.page()->mainFrame()->documentElement().findFirst(QLatin1String("input[type=text]"));
QTest::mouseClick(&view, Qt::LeftButton, 0, inputElement.geometry().center());
m_inputFieldsTestView = &view;
view.installEventFilter( this );
QTest::qWait(delay);
QVERIFY2(m_inputFieldTestPaintCount >= 3,
"The input field should have a blinking caret");
qApp->setAutoSipEnabled(autoSipEnabled);
}
void tst_QWebFrame::hitTestContent()
{
QString html("<html><body><p>A paragraph</p><br/><br/><br/><a href=\"about:blank\" target=\"_foo\" id=\"link\">link text</a></body></html>");
QWebPage page;
QWebFrame* frame = page.mainFrame();
frame->setHtml(html);
page.setViewportSize(QSize(200, 0)); const QWebElement linkElement = frame->documentElement().findFirst(QLatin1String("a#link"));
QWebHitTestResult result = frame->hitTestContent(linkElement.geometry().center());
QCOMPARE(result.linkText(), QString("link text"));
QWebElement link = result.linkElement();
QCOMPARE(link.attribute("target"), QString("_foo"));
}
void tst_QWebFrame::baseUrl_data()
{
QTest::addColumn<QString>("html");
QTest::addColumn<QUrl>("loadUrl");
QTest::addColumn<QUrl>("url");
QTest::addColumn<QUrl>("baseUrl");
QTest::newRow("null") << QString() << QUrl()
<< QUrl("about:blank") << QUrl("about:blank");
QTest::newRow("foo") << QString() << QUrl("http://foobar.baz/")
<< QUrl("http://foobar.baz/") << QUrl("http://foobar.baz/");
QString html = "<html>"
"<head>"
"<base href=\"http://foobaz.bar/\" />"
"</head>"
"</html>";
QTest::newRow("customBaseUrl") << html << QUrl("http://foobar.baz/")
<< QUrl("http://foobar.baz/") << QUrl("http://foobaz.bar/");
}
void tst_QWebFrame::baseUrl()
{
QFETCH(QString, html);
QFETCH(QUrl, loadUrl);
QFETCH(QUrl, url);
QFETCH(QUrl, baseUrl);
m_page->mainFrame()->setHtml(html, loadUrl);
QCOMPARE(m_page->mainFrame()->url(), url);
QCOMPARE(m_page->mainFrame()->baseUrl(), baseUrl);
}
void tst_QWebFrame::hasSetFocus()
{
QString html("<html><body><p>top</p>" \
"<iframe width='80%' height='30%'/>" \
"</body></html>");
QSignalSpy loadSpy(m_page, SIGNAL(loadFinished(bool)));
m_page->mainFrame()->setHtml(html);
waitForSignal(m_page->mainFrame(), SIGNAL(loadFinished(bool)), 200);
QCOMPARE(loadSpy.size(), 1);
QList<QWebFrame*> children = m_page->mainFrame()->childFrames();
QWebFrame* frame = children.at(0);
QString innerHtml("<html><body><p>another iframe</p>" \
"<iframe width='80%' height='30%'/>" \
"</body></html>");
frame->setHtml(innerHtml);
waitForSignal(frame, SIGNAL(loadFinished(bool)), 200);
QCOMPARE(loadSpy.size(), 2);
m_page->mainFrame()->setFocus();
QTRY_VERIFY(m_page->mainFrame()->hasFocus());
for (int i = 0; i < children.size(); ++i) {
children.at(i)->setFocus();
QTRY_VERIFY(children.at(i)->hasFocus());
QVERIFY(!m_page->mainFrame()->hasFocus());
}
m_page->mainFrame()->setFocus();
QTRY_VERIFY(m_page->mainFrame()->hasFocus());
}
void tst_QWebFrame::renderGeometry()
{
QString html("<html>" \
"<head><style>" \
"body, iframe { margin: 0px; border: none; }" \
"</style></head>" \
"<body><iframe width='100px' height='100px'/></body>" \
"</html>");
QWebPage page;
page.mainFrame()->setHtml(html);
QList<QWebFrame*> frames = page.mainFrame()->childFrames();
QWebFrame *frame = frames.at(0);
QString innerHtml("<body style='margin: 0px;'><img src='qrc:/image.png'/></body>");
frame->setHtml(innerHtml, QUrl("file:///path/to/file"));
waitForSignal(frame, SIGNAL(loadFinished(bool)), 200);
QPicture picture;
QSize size = page.mainFrame()->contentsSize();
page.setViewportSize(size);
QPainter painter1(&picture);
frame->render(&painter1, QWebFrame::ContentsLayer);
painter1.end();
QCOMPARE(size.width(), picture.boundingRect().width() + frame->scrollBarGeometry(Qt::Vertical).width());
QCOMPARE(size.height(), picture.boundingRect().height() + frame->scrollBarGeometry(Qt::Horizontal).height());
QPainter painter2(&picture);
frame->render(&painter2, QWebFrame::AllLayers);
painter2.end();
QCOMPARE(size.width(), picture.boundingRect().width()); QCOMPARE(size.height(), picture.boundingRect().height()); }
class DummyPaintEngine: public QPaintEngine {
public:
DummyPaintEngine()
: QPaintEngine(QPaintEngine::AllFeatures)
, renderHints(0)
{
}
bool begin(QPaintDevice*)
{
setActive(true);
return true;
}
bool end()
{
setActive(false);
return false;
}
void updateState(const QPaintEngineState& state)
{
renderHints = state.renderHints();
}
void drawPath(const QPainterPath&) { }
void drawPixmap(const QRectF&, const QPixmap&, const QRectF&) { }
QPaintEngine::Type type() const
{
return static_cast<QPaintEngine::Type>(QPaintEngine::User + 2);
}
QPainter::RenderHints renderHints;
};
class DummyPaintDevice: public QPaintDevice {
public:
DummyPaintDevice()
: QPaintDevice()
, m_engine(new DummyPaintEngine)
{
}
~DummyPaintDevice()
{
delete m_engine;
}
QPaintEngine* paintEngine() const
{
return m_engine;
}
QPainter::RenderHints renderHints() const
{
return m_engine->renderHints;
}
protected:
int metric(PaintDeviceMetric metric) const;
private:
DummyPaintEngine* m_engine;
friend class DummyPaintEngine;
};
int DummyPaintDevice::metric(PaintDeviceMetric metric) const
{
switch (metric) {
case PdmWidth:
return 400;
break;
case PdmHeight:
return 200;
break;
case PdmNumColors:
return INT_MAX;
break;
case PdmDepth:
return 32;
break;
default:
break;
}
return 0;
}
void tst_QWebFrame::renderHints()
{
QString html("<html><body><p>Hello, world!</p></body></html>");
QWebPage page;
page.mainFrame()->setHtml(html);
page.setViewportSize(page.mainFrame()->contentsSize());
DummyPaintDevice buffer;
QPainter painter(&buffer);
painter.setRenderHint(QPainter::TextAntialiasing, false);
page.mainFrame()->render(&painter);
QVERIFY(!(buffer.renderHints() & QPainter::TextAntialiasing));
QVERIFY(!(buffer.renderHints() & QPainter::SmoothPixmapTransform));
QVERIFY(!(buffer.renderHints() & QPainter::HighQualityAntialiasing));
painter.setRenderHint(QPainter::TextAntialiasing, true);
page.mainFrame()->render(&painter);
QVERIFY(buffer.renderHints() & QPainter::TextAntialiasing);
QVERIFY(!(buffer.renderHints() & QPainter::SmoothPixmapTransform));
QVERIFY(!(buffer.renderHints() & QPainter::HighQualityAntialiasing));
painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
page.mainFrame()->render(&painter);
QVERIFY(buffer.renderHints() & QPainter::TextAntialiasing);
QVERIFY(buffer.renderHints() & QPainter::SmoothPixmapTransform);
QVERIFY(!(buffer.renderHints() & QPainter::HighQualityAntialiasing));
painter.setRenderHint(QPainter::HighQualityAntialiasing, true);
page.mainFrame()->render(&painter);
QVERIFY(buffer.renderHints() & QPainter::TextAntialiasing);
QVERIFY(buffer.renderHints() & QPainter::SmoothPixmapTransform);
QVERIFY(buffer.renderHints() & QPainter::HighQualityAntialiasing);
}
void tst_QWebFrame::scrollPosition()
{
QString html("<html><body><img src='qrc:/image.png' height=500 width=500/></body></html>");
QWebPage page;
page.setViewportSize(QSize(200, 200));
QWebFrame* frame = page.mainFrame();
frame->setHtml(html);
frame->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
frame->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
frame->setScrollPosition(QPoint(23, 29));
QCOMPARE(frame->scrollPosition().x(), 23);
QCOMPARE(frame->scrollPosition().y(), 29);
int x = frame->evaluateJavaScript("window.scrollX").toInt();
int y = frame->evaluateJavaScript("window.scrollY").toInt();
QCOMPARE(x, 23);
QCOMPARE(y, 29);
}
void tst_QWebFrame::scrollToAnchor()
{
QWebPage page;
page.setViewportSize(QSize(480, 800));
QWebFrame* frame = page.mainFrame();
QString html("<html><body><p style=\"margin-bottom: 1500px;\">Hello.</p>"
"<p><a id=\"foo\">This</a> is an anchor</p>"
"<p style=\"margin-bottom: 1500px;\"><a id=\"bar\">This</a> is another anchor</p>"
"</body></html>");
frame->setHtml(html);
frame->setScrollPosition(QPoint(0, 0));
QCOMPARE(frame->scrollPosition().x(), 0);
QCOMPARE(frame->scrollPosition().y(), 0);
QWebElement fooAnchor = frame->findFirstElement("a[id=foo]");
frame->scrollToAnchor("foo");
QCOMPARE(frame->scrollPosition().y(), fooAnchor.geometry().top());
frame->scrollToAnchor("bar");
frame->scrollToAnchor("foo");
QCOMPARE(frame->scrollPosition().y(), fooAnchor.geometry().top());
frame->scrollToAnchor("top");
QCOMPARE(frame->scrollPosition().y(), 0);
frame->scrollToAnchor("bar");
frame->scrollToAnchor("notexist");
QVERIFY(frame->scrollPosition().y() != 0);
}
void tst_QWebFrame::scrollbarsOff()
{
QWebView view;
QWebFrame* mainFrame = view.page()->mainFrame();
mainFrame->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
mainFrame->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
QString html("<script>" \
" function checkScrollbar() {" \
" if (innerWidth === document.documentElement.offsetWidth)" \
" document.getElementById('span1').innerText = 'SUCCESS';" \
" else" \
" document.getElementById('span1').innerText = 'FAIL';" \
" }" \
"</script>" \
"<body>" \
" <div style='margin-top:1000px ; margin-left:1000px'>" \
" <a id='offscreen' href='a'>End</a>" \
" </div>" \
"<span id='span1'></span>" \
"</body>");
QSignalSpy loadSpy(&view, SIGNAL(loadFinished(bool)));
view.setHtml(html);
::waitForSignal(&view, SIGNAL(loadFinished(bool)), 200);
QCOMPARE(loadSpy.count(), 1);
mainFrame->evaluateJavaScript("checkScrollbar();");
QCOMPARE(mainFrame->documentElement().findAll("span").at(0).toPlainText(), QString("SUCCESS"));
}
void tst_QWebFrame::horizontalScrollAfterBack()
{
QWebView view;
QWebFrame* frame = view.page()->mainFrame();
QSignalSpy loadSpy(view.page(), SIGNAL(loadFinished(bool)));
view.page()->settings()->setMaximumPagesInCache(2);
frame->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAsNeeded);
frame->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAsNeeded);
view.load(QUrl("qrc:/testiframe2.html"));
view.resize(200, 200);
QTRY_COMPARE(loadSpy.count(), 1);
QTRY_VERIFY((frame->scrollBarGeometry(Qt::Horizontal)).height());
view.load(QUrl("qrc:/testiframe.html"));
QTRY_COMPARE(loadSpy.count(), 2);
view.page()->triggerAction(QWebPage::Back);
QTRY_COMPARE(loadSpy.count(), 3);
QTRY_VERIFY((frame->scrollBarGeometry(Qt::Horizontal)).height());
}
void tst_QWebFrame::evaluateWillCauseRepaint()
{
QWebView view;
QString html("<html><body>top<div id=\"junk\" style=\"display: block;\">"
"junk</div>bottom</body></html>");
view.setHtml(html);
view.show();
QTest::qWaitForWindowExposed(&view);
view.page()->mainFrame()->evaluateJavaScript(
"document.getElementById('junk').style.display = 'none';");
::waitForSignal(view.page(), SIGNAL(repaintRequested(QRect)));
}
void tst_QWebFrame::setContent_data()
{
QTest::addColumn<QString>("mimeType");
QTest::addColumn<QByteArray>("testContents");
QTest::addColumn<QString>("expected");
QString str = QString::fromUtf8("ὕαλον ϕαγεῖν δύναμαι· τοῦτο οὔ με βλάπτει");
QTest::newRow("UTF-8 plain text") << "text/plain; charset=utf-8" << str.toUtf8() << str;
QTextCodec *utf16 = QTextCodec::codecForName("UTF-16");
if (utf16)
QTest::newRow("UTF-16 plain text") << "text/plain; charset=utf-16" << utf16->fromUnicode(str) << str;
str = QString::fromUtf8("Une chaîne de caractères à sa façon.");
QTest::newRow("latin-1 plain text") << "text/plain; charset=iso-8859-1" << str.toLatin1() << str;
}
void tst_QWebFrame::setContent()
{
QFETCH(QString, mimeType);
QFETCH(QByteArray, testContents);
QFETCH(QString, expected);
m_view->setContent(testContents, mimeType);
QWebFrame* mainFrame = m_view->page()->mainFrame();
QCOMPARE(expected , mainFrame->toPlainText());
}
class CacheNetworkAccessManager : public QNetworkAccessManager {
public:
CacheNetworkAccessManager(QObject* parent = 0)
: QNetworkAccessManager(parent)
, m_lastCacheLoad(QNetworkRequest::PreferNetwork)
{
}
virtual QNetworkReply* createRequest(Operation, const QNetworkRequest& request, QIODevice*)
{
QVariant cacheLoad = request.attribute(QNetworkRequest::CacheLoadControlAttribute);
if (cacheLoad.isValid())
m_lastCacheLoad = static_cast<QNetworkRequest::CacheLoadControl>(cacheLoad.toUInt());
else
m_lastCacheLoad = QNetworkRequest::PreferNetwork; return new FakeReply(request, this);
}
QNetworkRequest::CacheLoadControl lastCacheLoad() const
{
return m_lastCacheLoad;
}
private:
QNetworkRequest::CacheLoadControl m_lastCacheLoad;
};
void tst_QWebFrame::setCacheLoadControlAttribute()
{
QWebPage page;
CacheNetworkAccessManager* manager = new CacheNetworkAccessManager(&page);
page.setNetworkAccessManager(manager);
QWebFrame* frame = page.mainFrame();
QNetworkRequest request(QUrl("http://abcdef.abcdef/"));
request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysCache);
frame->load(request);
QCOMPARE(manager->lastCacheLoad(), QNetworkRequest::AlwaysCache);
request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
frame->load(request);
QCOMPARE(manager->lastCacheLoad(), QNetworkRequest::PreferCache);
request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork);
frame->load(request);
QCOMPARE(manager->lastCacheLoad(), QNetworkRequest::AlwaysNetwork);
request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork);
frame->load(request);
QCOMPARE(manager->lastCacheLoad(), QNetworkRequest::PreferNetwork);
}
void tst_QWebFrame::setUrlWithPendingLoads()
{
QWebPage page;
page.mainFrame()->setHtml("<img src='dummy:'/>");
page.mainFrame()->setUrl(QUrl("about:blank"));
}
void tst_QWebFrame::setUrlWithFragment_data()
{
QTest::addColumn<QUrl>("previousUrl");
QTest::newRow("empty") << QUrl();
QTest::newRow("same URL no fragment") << QUrl("qrc:/test1.html");
QTest::newRow("same URL with same fragment") << QUrl("qrc:/test1.html#");
QTest::newRow("same URL with different fragment") << QUrl("qrc:/test1.html#anotherFragment");
QTest::newRow("another URL") << QUrl("qrc:/test2.html");
}
void tst_QWebFrame::setUrlWithFragment()
{
QFETCH(QUrl, previousUrl);
QWebPage page;
QWebFrame* frame = page.mainFrame();
if (!previousUrl.isEmpty()) {
frame->load(previousUrl);
::waitForSignal(frame, SIGNAL(loadFinished(bool)));
QCOMPARE(frame->url(), previousUrl);
}
QSignalSpy spy(frame, SIGNAL(loadFinished(bool)));
const QUrl url("qrc:/test1.html#");
QVERIFY(!url.fragment().isNull());
frame->setUrl(url);
::waitForSignal(frame, SIGNAL(loadFinished(bool)));
QCOMPARE(spy.count(), 1);
QVERIFY(!frame->toPlainText().isEmpty());
QCOMPARE(frame->requestedUrl(), url);
QCOMPARE(frame->url(), url);
}
void tst_QWebFrame::setUrlToEmpty()
{
int expectedLoadFinishedCount = 0;
const QUrl aboutBlank("about:blank");
const QUrl url("qrc:/test2.html");
QWebPage page;
QWebFrame* frame = page.mainFrame();
QCOMPARE(frame->url(), QUrl());
QCOMPARE(frame->requestedUrl(), QUrl());
QCOMPARE(frame->baseUrl(), QUrl());
QSignalSpy spy(frame, SIGNAL(loadFinished(bool)));
frame->setUrl(url);
expectedLoadFinishedCount++;
::waitForSignal(frame, SIGNAL(loadFinished(bool)));
QCOMPARE(spy.count(), expectedLoadFinishedCount);
QCOMPARE(frame->url(), url);
QCOMPARE(frame->requestedUrl(), url);
QCOMPARE(frame->baseUrl(), url);
frame->setUrl(QUrl());
expectedLoadFinishedCount++;
QCOMPARE(spy.count(), expectedLoadFinishedCount);
QCOMPARE(frame->url(), aboutBlank);
QCOMPARE(frame->requestedUrl(), QUrl());
QCOMPARE(frame->baseUrl(), aboutBlank);
frame->setUrl(url);
expectedLoadFinishedCount++;
::waitForSignal(frame, SIGNAL(loadFinished(bool)));
QCOMPARE(spy.count(), expectedLoadFinishedCount);
QCOMPARE(frame->url(), url);
QCOMPARE(frame->requestedUrl(), url);
QCOMPARE(frame->baseUrl(), url);
frame->load(QUrl());
expectedLoadFinishedCount++;
QCOMPARE(spy.count(), expectedLoadFinishedCount);
QCOMPARE(frame->url(), aboutBlank);
QCOMPARE(frame->requestedUrl(), QUrl());
QCOMPARE(frame->baseUrl(), aboutBlank);
}
void tst_QWebFrame::setUrlToInvalid()
{
QWebPage page;
QWebFrame* frame = page.mainFrame();
const QUrl invalidUrl("http:/example.com");
QVERIFY(!invalidUrl.isEmpty());
QVERIFY(invalidUrl != QUrl());
const QUrl validUrl("http://example.com/");
frame->setUrl(invalidUrl);
QCOMPARE(frame->url(), validUrl);
QCOMPARE(frame->requestedUrl(), validUrl);
QCOMPARE(frame->baseUrl(), validUrl);
const QUrl aboutBlank("about:blank");
const QUrl anotherInvalidUrl("1http://bugs.webkit.org");
QVERIFY(!anotherInvalidUrl.isEmpty()); QVERIFY(!anotherInvalidUrl.isValid());
QCOMPARE(anotherInvalidUrl.toEncoded(), QUrl().toEncoded());
frame->setUrl(anotherInvalidUrl);
QCOMPARE(frame->url(), aboutBlank);
QCOMPARE(frame->requestedUrl().toEncoded(), anotherInvalidUrl.toEncoded());
QCOMPARE(frame->baseUrl(), aboutBlank);
}
void tst_QWebFrame::setUrlHistory()
{
const QUrl aboutBlank("about:blank");
QUrl url;
int expectedLoadFinishedCount = 0;
QWebFrame* frame = m_page->mainFrame();
QSignalSpy spy(frame, SIGNAL(loadFinished(bool)));
QCOMPARE(m_page->history()->count(), 0);
frame->setUrl(QUrl());
expectedLoadFinishedCount++;
QCOMPARE(spy.count(), expectedLoadFinishedCount);
QCOMPARE(frame->url(), aboutBlank);
QCOMPARE(frame->requestedUrl(), QUrl());
QCOMPARE(m_page->history()->count(), 0);
url = QUrl("http://non.existant/");
frame->setUrl(url);
::waitForSignal(m_page, SIGNAL(loadFinished(bool)));
expectedLoadFinishedCount++;
QCOMPARE(spy.count(), expectedLoadFinishedCount);
QCOMPARE(frame->url(), url);
QCOMPARE(frame->requestedUrl(), url);
QCOMPARE(m_page->history()->count(), 0);
url = QUrl("qrc:/test1.html");
frame->setUrl(url);
::waitForSignal(m_page, SIGNAL(loadFinished(bool)));
expectedLoadFinishedCount++;
QCOMPARE(spy.count(), expectedLoadFinishedCount);
QCOMPARE(frame->url(), url);
QCOMPARE(frame->requestedUrl(), url);
QCOMPARE(m_page->history()->count(), 1);
frame->setUrl(QUrl());
expectedLoadFinishedCount++;
QCOMPARE(spy.count(), expectedLoadFinishedCount);
QCOMPARE(frame->url(), aboutBlank);
QCOMPARE(frame->requestedUrl(), QUrl());
QCOMPARE(m_page->history()->count(), 1);
url = QUrl("qrc:/test1.html");
frame->setUrl(url);
::waitForSignal(m_page, SIGNAL(loadFinished(bool)));
expectedLoadFinishedCount++;
QCOMPARE(spy.count(), expectedLoadFinishedCount);
QCOMPARE(frame->url(), url);
QCOMPARE(frame->requestedUrl(), url);
QCOMPARE(m_page->history()->count(), 1);
url = QUrl("qrc:/test2.html");
frame->setUrl(url);
::waitForSignal(m_page, SIGNAL(loadFinished(bool)));
expectedLoadFinishedCount++;
QCOMPARE(spy.count(), expectedLoadFinishedCount);
QCOMPARE(frame->url(), url);
QCOMPARE(frame->requestedUrl(), url);
QCOMPARE(m_page->history()->count(), 2);
}
void tst_QWebFrame::setUrlUsingStateObject()
{
const QUrl aboutBlank("about:blank");
QUrl url;
QWebFrame* frame = m_page->mainFrame();
QSignalSpy urlChangedSpy(frame, SIGNAL(urlChanged(QUrl)));
int expectedUrlChangeCount = 0;
QCOMPARE(m_page->history()->count(), 0);
url = QUrl("qrc:/test1.html");
frame->setUrl(url);
waitForSignal(m_page, SIGNAL(loadFinished(bool)));
expectedUrlChangeCount++;
QCOMPARE(urlChangedSpy.count(), expectedUrlChangeCount);
QCOMPARE(frame->url(), url);
QCOMPARE(m_page->history()->count(), 1);
frame->evaluateJavaScript("window.history.pushState(null,'push', 'navigate/to/here')");
expectedUrlChangeCount++;
QCOMPARE(urlChangedSpy.count(), expectedUrlChangeCount);
QCOMPARE(frame->url(), QUrl("qrc:/navigate/to/here"));
QCOMPARE(m_page->history()->count(), 2);
QVERIFY(m_page->history()->canGoBack());
frame->evaluateJavaScript("window.history.replaceState(null,'replace', 'another/location')");
expectedUrlChangeCount++;
QCOMPARE(urlChangedSpy.count(), expectedUrlChangeCount);
QCOMPARE(frame->url(), QUrl("qrc:/navigate/to/another/location"));
QCOMPARE(m_page->history()->count(), 2);
QVERIFY(!m_page->history()->canGoForward());
QVERIFY(m_page->history()->canGoBack());
frame->evaluateJavaScript("window.history.back()");
QTest::qWait(100);
expectedUrlChangeCount++;
QCOMPARE(urlChangedSpy.count(), expectedUrlChangeCount);
QCOMPARE(frame->url(), QUrl("qrc:/test1.html"));
QVERIFY(m_page->history()->canGoForward());
QVERIFY(!m_page->history()->canGoBack());
}
void tst_QWebFrame::setUrlSameUrl()
{
const QUrl url1("qrc:/test1.html");
const QUrl url2("qrc:/test2.html");
QWebPage page;
QWebFrame* frame = page.mainFrame();
FakeNetworkManager* networkManager = new FakeNetworkManager(&page);
page.setNetworkAccessManager(networkManager);
QSignalSpy spy(frame, SIGNAL(loadFinished(bool)));
frame->setUrl(url1);
waitForSignal(frame, SIGNAL(loadFinished(bool)));
QVERIFY(frame->url() != url1); QCOMPARE(frame->url(), url2);
QCOMPARE(spy.count(), 1);
frame->setUrl(url1);
waitForSignal(frame, SIGNAL(loadFinished(bool)));
QVERIFY(frame->url() != url1);
QCOMPARE(frame->url(), url2);
QCOMPARE(spy.count(), 2);
frame->setUrl(url2);
waitForSignal(frame, SIGNAL(loadFinished(bool)));
QCOMPARE(frame->url(), url2);
QCOMPARE(spy.count(), 3);
frame->setUrl(url1);
waitForSignal(frame, SIGNAL(loadFinished(bool)));
QCOMPARE(frame->url(), url2);
QCOMPARE(spy.count(), 4);
}
static inline QUrl extractBaseUrl(const QUrl& url)
{
return url.resolved(QUrl());
}
void tst_QWebFrame::setUrlThenLoads_data()
{
QTest::addColumn<QUrl>("url");
QTest::addColumn<QUrl>("baseUrl");
QTest::newRow("resource file") << QUrl("qrc:/test1.html") << extractBaseUrl(QUrl("qrc:/test1.html"));
QTest::newRow("base specified in HTML") << QUrl("data:text/html,<head><base href=\"http://different.base/\"></head>") << QUrl("http://different.base/");
}
void tst_QWebFrame::setUrlThenLoads()
{
QFETCH(QUrl, url);
QFETCH(QUrl, baseUrl);
QWebFrame* frame = m_page->mainFrame();
QSignalSpy urlChangedSpy(frame, SIGNAL(urlChanged(QUrl)));
QSignalSpy startedSpy(frame, SIGNAL(loadStarted()));
QSignalSpy finishedSpy(frame, SIGNAL(loadFinished(bool)));
frame->setUrl(url);
QCOMPARE(startedSpy.count(), 1);
::waitForSignal(frame, SIGNAL(urlChanged(QUrl)));
QCOMPARE(urlChangedSpy.count(), 1);
QVERIFY(finishedSpy.at(0).first().toBool());
QCOMPARE(frame->url(), url);
QCOMPARE(frame->requestedUrl(), url);
QCOMPARE(frame->baseUrl(), baseUrl);
const QUrl urlToLoad1("qrc:/test2.html");
const QUrl urlToLoad2("qrc:/test1.html");
frame->load(urlToLoad1);
QCOMPARE(startedSpy.count(), 2);
QCOMPARE(frame->url(), url);
QCOMPARE(frame->requestedUrl(), urlToLoad1);
QCOMPARE(frame->baseUrl(), baseUrl);
::waitForSignal(frame, SIGNAL(urlChanged(QUrl)));
QCOMPARE(urlChangedSpy.count(), 2);
QVERIFY(finishedSpy.at(1).first().toBool());
QCOMPARE(frame->url(), urlToLoad1);
QCOMPARE(frame->requestedUrl(), urlToLoad1);
QCOMPARE(frame->baseUrl(), extractBaseUrl(urlToLoad1));
frame->load(urlToLoad2);
QCOMPARE(startedSpy.count(), 3);
QCOMPARE(frame->url(), urlToLoad1);
QCOMPARE(frame->requestedUrl(), urlToLoad2);
QCOMPARE(frame->baseUrl(), extractBaseUrl(urlToLoad1));
::waitForSignal(frame, SIGNAL(urlChanged(QUrl)));
QCOMPARE(urlChangedSpy.count(), 3);
QVERIFY(finishedSpy.at(2).first().toBool());
QCOMPARE(frame->url(), urlToLoad2);
QCOMPARE(frame->requestedUrl(), urlToLoad2);
QCOMPARE(frame->baseUrl(), extractBaseUrl(urlToLoad2));
}
void tst_QWebFrame::loadFinishedAfterNotFoundError()
{
QWebPage page;
QWebFrame* frame = page.mainFrame();
QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
FakeNetworkManager* networkManager = new FakeNetworkManager(&page);
page.setNetworkAccessManager(networkManager);
frame->setUrl(FakeReply::urlFor404ErrorWithoutContents);
QTRY_COMPARE(spy.count(), 1);
const bool wasLoadOk = spy.at(0).at(0).toBool();
QVERIFY(!wasLoadOk);
}
class URLSetter : public QObject {
Q_OBJECT
public:
enum Signal {
LoadStarted,
LoadFinished,
ProvisionalLoad
};
enum Type {
UseLoad,
UseSetUrl
};
URLSetter(QWebFrame*, Signal, Type, const QUrl&);
public Q_SLOTS:
void execute();
Q_SIGNALS:
void finished();
private:
QWebFrame* m_frame;
QUrl m_url;
Type m_type;
};
Q_DECLARE_METATYPE(URLSetter::Signal)
Q_DECLARE_METATYPE(URLSetter::Type)
URLSetter::URLSetter(QWebFrame* frame, Signal signal, URLSetter::Type type, const QUrl& url)
: m_frame(frame), m_url(url), m_type(type)
{
if (signal == LoadStarted)
connect(m_frame, SIGNAL(loadStarted()), SLOT(execute()));
else if (signal == LoadFinished)
connect(m_frame, SIGNAL(loadFinished(bool)), SLOT(execute()));
else
connect(m_frame, SIGNAL(provisionalLoad()), SLOT(execute()));
}
void URLSetter::execute()
{
m_frame->disconnect(this);
if (m_type == URLSetter::UseLoad)
m_frame->load(m_url);
else
m_frame->setUrl(m_url);
connect(m_frame, SIGNAL(loadFinished(bool)), SIGNAL(finished()));
}
void tst_QWebFrame::loadInSignalHandlers_data()
{
QTest::addColumn<URLSetter::Type>("type");
QTest::addColumn<URLSetter::Signal>("signal");
QTest::addColumn<QUrl>("url");
const QUrl validUrl("qrc:/test2.html");
const QUrl invalidUrl("qrc:/invalid");
QTest::newRow("call load() in loadStarted() after valid url") << URLSetter::UseLoad << URLSetter::LoadStarted << validUrl;
QTest::newRow("call load() in loadStarted() after invalid url") << URLSetter::UseLoad << URLSetter::LoadStarted << invalidUrl;
QTest::newRow("call load() in loadFinished() after valid url") << URLSetter::UseLoad << URLSetter::LoadFinished << validUrl;
QTest::newRow("call load() in loadFinished() after invalid url") << URLSetter::UseLoad << URLSetter::LoadFinished << invalidUrl;
QTest::newRow("call load() in provisionalLoad() after valid url") << URLSetter::UseLoad << URLSetter::ProvisionalLoad << validUrl;
QTest::newRow("call load() in provisionalLoad() after invalid url") << URLSetter::UseLoad << URLSetter::ProvisionalLoad << invalidUrl;
QTest::newRow("call setUrl() in loadStarted() after valid url") << URLSetter::UseSetUrl << URLSetter::LoadStarted << validUrl;
QTest::newRow("call setUrl() in loadStarted() after invalid url") << URLSetter::UseSetUrl << URLSetter::LoadStarted << invalidUrl;
QTest::newRow("call setUrl() in loadFinished() after valid url") << URLSetter::UseSetUrl << URLSetter::LoadFinished << validUrl;
QTest::newRow("call setUrl() in loadFinished() after invalid url") << URLSetter::UseSetUrl << URLSetter::LoadFinished << invalidUrl;
QTest::newRow("call setUrl() in provisionalLoad() after valid url") << URLSetter::UseSetUrl << URLSetter::ProvisionalLoad << validUrl;
QTest::newRow("call setUrl() in provisionalLoad() after invalid url") << URLSetter::UseSetUrl << URLSetter::ProvisionalLoad << invalidUrl;
}
void tst_QWebFrame::loadInSignalHandlers()
{
QFETCH(URLSetter::Type, type);
QFETCH(URLSetter::Signal, signal);
QFETCH(QUrl, url);
QWebFrame* frame = m_page->mainFrame();
const QUrl urlForSetter("qrc:/test1.html");
URLSetter setter(frame, signal, type, urlForSetter);
frame->load(url);
waitForSignal(&setter, SIGNAL(finished()), 200);
QCOMPARE(frame->url(), urlForSetter);
}
QTEST_MAIN(tst_QWebFrame)
#include "tst_qwebframe.moc"