1#include "../util.h"
2#include <QAction>
3#include <QColor>
4#include <QDebug>
5#include <QDeclarativeComponent>
6#include <QDeclarativeEngine>
7#include <QDeclarativeItem>
8#include <QDeclarativeProperty>
9#include <QDeclarativeView>
10#include <QDir>
11#include <QGraphicsWebView>
12#include <QTest>
13#include <QVariant>
14#include <QWebFrame>
15#include "qdeclarativewebview_p.h"
16
17QT_BEGIN_NAMESPACE
18
19class tst_QDeclarativeWebView : public QObject {
20    Q_OBJECT
21
22public:
23    tst_QDeclarativeWebView();
24
25private slots:
26    void cleanupTestCase();
27
28    void basicProperties();
29    void elementAreaAt();
30    void historyNav();
31    void javaScript();
32    void loadError();
33    void multipleWindows();
34    void newWindowComponent();
35    void newWindowParent();
36    void preferredWidthTest();
37    void preferredHeightTest();
38    void preferredWidthDefaultTest();
39    void preferredHeightDefaultTest();
40    void pressGrabTime();
41    void renderingEnabled();
42    void setHtml();
43    void settings();
44#if QT_VERSION >= 0x040703
45    void backgroundColor();
46#endif
47
48private:
49    void checkNoErrors(const QDeclarativeComponent&);
50    QString tmpDir() const
51    {
52        static QString tmpd = QDir::tempPath() + "/tst_qdeclarativewebview-"
53            + QDateTime::currentDateTime().toString(QLatin1String("yyyyMMddhhmmss"));
54        return tmpd;
55    }
56};
57
58tst_QDeclarativeWebView::tst_QDeclarativeWebView()
59{
60    Q_UNUSED(waitForSignal)
61}
62
63static QString strippedHtml(QString html)
64{
65    html.replace(QRegExp("\\s+"), "");
66    return html;
67}
68
69static QString fileContents(const QString& filename)
70{
71    QFile file(filename);
72    file.open(QIODevice::ReadOnly);
73    return QString::fromUtf8(file.readAll());
74}
75
76static void removeRecursive(const QString& dirname)
77{
78    QDir dir(dirname);
79    QFileInfoList entries(dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot));
80    for (int i = 0; i < entries.count(); ++i)
81        if (entries[i].isDir())
82            removeRecursive(entries[i].filePath());
83        else
84            dir.remove(entries[i].fileName());
85    QDir().rmdir(dirname);
86}
87
88void tst_QDeclarativeWebView::cleanupTestCase()
89{
90    removeRecursive(tmpDir());
91}
92
93void tst_QDeclarativeWebView::basicProperties()
94{
95    QDeclarativeEngine engine;
96    QDeclarativeComponent component(&engine, QUrl("qrc:///resources/basic.qml"));
97    checkNoErrors(component);
98    QWebSettings::enablePersistentStorage(tmpDir());
99
100    QObject* wv = component.create();
101    QVERIFY(wv);
102    QTRY_COMPARE(wv->property("progress").toDouble(), 1.0);
103    QCOMPARE(wv->property("title").toString(), QLatin1String("Basic"));
104    QTRY_COMPARE(qvariant_cast<QPixmap>(wv->property("icon")).width(), 48);
105    QEXPECT_FAIL("", "'icon' property isn't working", Continue);
106    QCOMPARE(qvariant_cast<QPixmap>(wv->property("icon")), QPixmap("qrc:///resources/basic.png"));
107    QCOMPARE(wv->property("statusText").toString(), QLatin1String("status here"));
108    QCOMPARE(strippedHtml(fileContents(":/resources/basic.html")), strippedHtml(wv->property("html").toString()));
109    QEXPECT_FAIL("", "TODO: get preferred width from QGraphicsWebView result", Continue);
110    QCOMPARE(wv->property("preferredWidth").toInt(), 0);
111    QEXPECT_FAIL("", "TODO: get preferred height from QGraphicsWebView result", Continue);
112    QCOMPARE(wv->property("preferredHeight").toInt(), 0);
113    QCOMPARE(wv->property("url").toUrl(), QUrl("qrc:///resources/basic.html"));
114    QCOMPARE(wv->property("status").toInt(), int(QDeclarativeWebView::Ready));
115
116    QAction* reloadAction = wv->property("reload").value<QAction*>();
117    QVERIFY(reloadAction);
118    QVERIFY(reloadAction->isEnabled());
119    QAction* backAction = wv->property("back").value<QAction*>();
120    QVERIFY(backAction);
121    QVERIFY(!backAction->isEnabled());
122    QAction* forwardAction = wv->property("forward").value<QAction*>();
123    QVERIFY(forwardAction);
124    QVERIFY(!forwardAction->isEnabled());
125    QAction* stopAction = wv->property("stop").value<QAction*>();
126    QVERIFY(stopAction);
127    QVERIFY(!stopAction->isEnabled());
128
129    wv->setProperty("pixelCacheSize", 0); // mainly testing that it doesn't crash or anything!
130    QCOMPARE(wv->property("pixelCacheSize").toInt(), 0);
131    reloadAction->trigger();
132    QTRY_COMPARE(wv->property("progress").toDouble(), 1.0);
133}
134
135void tst_QDeclarativeWebView::elementAreaAt()
136{
137    QSKIP("This test should be changed to test 'heuristicZoom' instead.", SkipAll);
138    QDeclarativeEngine engine;
139    QDeclarativeComponent component(&engine, QUrl("qrc:///resources/elements.qml"));
140    checkNoErrors(component);
141    QDeclarativeWebView* wv = qobject_cast<QDeclarativeWebView*>(component.create());
142    QVERIFY(wv);
143    QTRY_COMPARE(wv->property("progress").toDouble(), 1.0);
144
145    // Areas from elements.html.
146//    const QRect areaA(1, 1, 75, 54);
147//    const QRect areaB(78, 3, 110, 50);
148//    const QRect wholeView(0, 0, 310, 100);
149//    const QRect areaBC(76, 1, 223, 54);
150
151//    QCOMPARE(wv->elementAreaAt(40, 30, 100, 100), areaA);
152//    QCOMPARE(wv->elementAreaAt(130, 30, 200, 100), areaB);
153//    QCOMPARE(wv->elementAreaAt(40, 30, 400, 400), wholeView);
154//    QCOMPARE(wv->elementAreaAt(130, 30, 280, 280), areaBC);
155//    QCOMPARE(wv->elementAreaAt(130, 30, 400, 400), wholeView);
156}
157
158void tst_QDeclarativeWebView::historyNav()
159{
160    QDeclarativeEngine engine;
161    QDeclarativeComponent component(&engine, QUrl("qrc:///resources/basic.qml"));
162    checkNoErrors(component);
163    QWebSettings::enablePersistentStorage(tmpDir());
164
165    QObject* wv = component.create();
166    QVERIFY(wv);
167
168    QAction* reloadAction = wv->property("reload").value<QAction*>();
169    QVERIFY(reloadAction);
170    QAction* backAction = wv->property("back").value<QAction*>();
171    QVERIFY(backAction);
172    QAction* forwardAction = wv->property("forward").value<QAction*>();
173    QVERIFY(forwardAction);
174    QAction* stopAction = wv->property("stop").value<QAction*>();
175    QVERIFY(stopAction);
176
177    for (int i = 1; i <= 2; ++i) {
178        QTRY_COMPARE(wv->property("progress").toDouble(), 1.0);
179        QCOMPARE(wv->property("title").toString(), QLatin1String("Basic"));
180        QTRY_COMPARE(qvariant_cast<QPixmap>(wv->property("icon")).width(), 48);
181        QEXPECT_FAIL("", "'icon' property isn't working", Continue);
182        QCOMPARE(qvariant_cast<QPixmap>(wv->property("icon")), QPixmap("qrc:///data/basic.png"));
183        QCOMPARE(wv->property("statusText").toString(), QLatin1String("status here"));
184        QCOMPARE(strippedHtml(fileContents(":/resources/basic.html")), strippedHtml(wv->property("html").toString()));
185        QEXPECT_FAIL("", "TODO: get preferred width from QGraphicsWebView result", Continue);
186        QCOMPARE(wv->property("preferredWidth").toDouble(), 0.0);
187        QCOMPARE(wv->property("url").toUrl(), QUrl("qrc:///resources/basic.html"));
188        QCOMPARE(wv->property("status").toInt(), int(QDeclarativeWebView::Ready));
189        QVERIFY(reloadAction->isEnabled());
190        QVERIFY(!backAction->isEnabled());
191        QVERIFY(!forwardAction->isEnabled());
192        QVERIFY(!stopAction->isEnabled());
193        reloadAction->trigger();
194    }
195
196    wv->setProperty("url", QUrl("qrc:///resources/forward.html"));
197    QTRY_COMPARE(wv->property("progress").toDouble(), 1.0);
198    QCOMPARE(wv->property("title").toString(), QLatin1String("Forward"));
199    QTRY_COMPARE(qvariant_cast<QPixmap>(wv->property("icon")).width(), 32);
200    QEXPECT_FAIL("", "'icon' property isn't working", Continue);
201    QCOMPARE(qvariant_cast<QPixmap>(wv->property("icon")), QPixmap("qrc:///resources/forward.png"));
202    QCOMPARE(strippedHtml(fileContents(":/resources/forward.html")), strippedHtml(wv->property("html").toString()));
203    QCOMPARE(wv->property("url").toUrl(), QUrl("qrc:///resources/forward.html"));
204    QCOMPARE(wv->property("status").toInt(), int(QDeclarativeWebView::Ready));
205    QCOMPARE(wv->property("statusText").toString(), QString());
206
207    QVERIFY(reloadAction->isEnabled());
208    QVERIFY(backAction->isEnabled());
209    QVERIFY(!forwardAction->isEnabled());
210    QVERIFY(!stopAction->isEnabled());
211
212    backAction->trigger();
213
214    QTRY_COMPARE(wv->property("progress").toDouble(), 1.0);
215    QCOMPARE(wv->property("title").toString(), QLatin1String("Basic"));
216    QCOMPARE(strippedHtml(fileContents(":/resources/basic.html")), strippedHtml(wv->property("html").toString()));
217    QCOMPARE(wv->property("url").toUrl(), QUrl("qrc:///resources/basic.html"));
218    QCOMPARE(wv->property("status").toInt(), int(QDeclarativeWebView::Ready));
219
220    QVERIFY(reloadAction->isEnabled());
221    QVERIFY(!backAction->isEnabled());
222    QVERIFY(forwardAction->isEnabled());
223    QVERIFY(!stopAction->isEnabled());
224}
225
226static inline QVariant callEvaluateJavaScript(QObject *object, const QString& snippet)
227{
228    QVariant result;
229    QMetaObject::invokeMethod(object, "evaluateJavaScript", Q_RETURN_ARG(QVariant, result), Q_ARG(QString, snippet));
230    return result;
231}
232
233void tst_QDeclarativeWebView::javaScript()
234{
235    QDeclarativeEngine engine;
236    QDeclarativeComponent component(&engine, QUrl("qrc:///resources/javaScript.qml"));
237    checkNoErrors(component);
238    QObject* wv = component.create();
239    QVERIFY(wv);
240    QTRY_COMPARE(wv->property("progress").toDouble(), 1.0);
241
242    QCOMPARE(callEvaluateJavaScript(wv, "123").toInt(), 123);
243    QCOMPARE(callEvaluateJavaScript(wv, "window.status").toString(), QLatin1String("status here"));
244    QCOMPARE(callEvaluateJavaScript(wv, "window.myjsname.qmlprop").toString(), QLatin1String("qmlvalue"));
245}
246
247void tst_QDeclarativeWebView::loadError()
248{
249    QDeclarativeEngine engine;
250    QDeclarativeComponent component(&engine, QUrl("qrc:///resources/loadError.qml"));
251    checkNoErrors(component);
252    QWebSettings::enablePersistentStorage(tmpDir());
253
254    QObject* wv = component.create();
255    QVERIFY(wv);
256    QAction* reloadAction = wv->property("reload").value<QAction*>();
257    QVERIFY(reloadAction);
258
259    for (int i = 1; i <= 2; ++i) {
260        QTRY_COMPARE(wv->property("progress").toDouble(), 1.0);
261        QCOMPARE(wv->property("title").toString(), QString());
262        QCOMPARE(wv->property("statusText").toString(), QString()); // HTML 'status bar' text, not error message
263        QCOMPARE(wv->property("url").toUrl(), QUrl("qrc:///resources/does-not-exist.html")); // Unlike QWebPage, which loses url
264        QCOMPARE(wv->property("status").toInt(), int(QDeclarativeWebView::Error));
265        reloadAction->trigger();
266    }
267}
268
269void tst_QDeclarativeWebView::multipleWindows()
270{
271    QSKIP("Rework this test to not depend on QDeclarativeGrid", SkipAll);
272    QDeclarativeEngine engine;
273    QDeclarativeComponent component(&engine, QUrl("qrc:///resources/newwindows.qml"));
274    checkNoErrors(component);
275
276//    QDeclarativeGrid *grid = qobject_cast<QDeclarativeGrid*>(component.create());
277//    QVERIFY(grid != 0);
278//    QTRY_COMPARE(grid->children().count(), 2+4); // Component, Loader (with 1 WebView), 4 new-window WebViews
279//    QDeclarativeItem* popup = qobject_cast<QDeclarativeItem*>(grid->children().at(2)); // first popup after Component and Loader.
280//    QVERIFY(popup != 0);
281//    QTRY_COMPARE(popup->x(), 150.0);
282}
283
284void tst_QDeclarativeWebView::newWindowComponent()
285{
286    QDeclarativeEngine engine;
287    QDeclarativeComponent component(&engine, QUrl("qrc:///resources/propertychanges.qml"));
288    checkNoErrors(component);
289    QDeclarativeItem* rootItem = qobject_cast<QDeclarativeItem*>(component.create());
290    QVERIFY(rootItem);
291    QObject* wv = rootItem->findChild<QObject*>("webView");
292    QVERIFY(wv);
293    QTRY_COMPARE(wv->property("progress").toDouble(), 1.0);
294
295    QDeclarativeComponent substituteComponent(&engine);
296    substituteComponent.setData("import QtQuick 1.0; WebView { objectName: 'newWebView'; url: 'basic.html'; }", QUrl::fromLocalFile(""));
297    QSignalSpy newWindowComponentSpy(wv, SIGNAL(newWindowComponentChanged()));
298
299    wv->setProperty("newWindowComponent", QVariant::fromValue(&substituteComponent));
300    QCOMPARE(wv->property("newWindowComponent"), QVariant::fromValue(&substituteComponent));
301    QCOMPARE(newWindowComponentSpy.count(), 1);
302
303    wv->setProperty("newWindowComponent", QVariant::fromValue(&substituteComponent));
304    QCOMPARE(newWindowComponentSpy.count(), 1);
305
306    wv->setProperty("newWindowComponent", QVariant::fromValue((QDeclarativeComponent*)0));
307    QCOMPARE(newWindowComponentSpy.count(), 2);
308}
309
310void tst_QDeclarativeWebView::newWindowParent()
311{
312    QDeclarativeEngine engine;
313    QDeclarativeComponent component(&engine, QUrl("qrc:///resources/propertychanges.qml"));
314    checkNoErrors(component);
315    QDeclarativeItem* rootItem = qobject_cast<QDeclarativeItem*>(component.create());
316    QVERIFY(rootItem);
317    QObject* wv = rootItem->findChild<QObject*>("webView");
318    QVERIFY(wv);
319    QTRY_COMPARE(wv->property("progress").toDouble(), 1.0);
320
321    QDeclarativeItem* oldWindowParent = rootItem->findChild<QDeclarativeItem*>("oldWindowParent");
322    QCOMPARE(qvariant_cast<QDeclarativeItem*>(wv->property("newWindowParent")), oldWindowParent);
323    QSignalSpy newWindowParentSpy(wv, SIGNAL(newWindowParentChanged()));
324
325    QDeclarativeItem* newWindowParent = rootItem->findChild<QDeclarativeItem*>("newWindowParent");
326    wv->setProperty("newWindowParent", QVariant::fromValue(newWindowParent));
327    QVERIFY(newWindowParent);
328    QVERIFY(oldWindowParent);
329    QCOMPARE(oldWindowParent->childItems().count(), 0);
330    QCOMPARE(wv->property("newWindowParent"), QVariant::fromValue(newWindowParent));
331    QCOMPARE(newWindowParentSpy.count(), 1);
332
333    wv->setProperty("newWindowParent", QVariant::fromValue(newWindowParent));
334    QCOMPARE(newWindowParentSpy.count(), 1);
335
336    wv->setProperty("newWindowParent", QVariant::fromValue((QDeclarativeItem*)0));
337    QCOMPARE(newWindowParentSpy.count(), 2);
338}
339
340void tst_QDeclarativeWebView::preferredWidthTest()
341{
342    QDeclarativeEngine engine;
343    QDeclarativeComponent component(&engine, QUrl("qrc:///resources/webviewtest.qml"));
344    checkNoErrors(component);
345    QObject* wv = component.create();
346    QVERIFY(wv);
347    wv->setProperty("testUrl", QUrl("qrc:///resources/sample.html"));
348    QCOMPARE(wv->property("prefWidth").toInt(), 600);
349}
350
351void tst_QDeclarativeWebView::preferredHeightTest()
352{
353    QDeclarativeEngine engine;
354    QDeclarativeComponent component(&engine, QUrl("qrc:///resources/webviewtest.qml"));
355    checkNoErrors(component);
356    QObject* wv = component.create();
357    QVERIFY(wv);
358    wv->setProperty("testUrl", QUrl("qrc:///resources/sample.html"));
359    QCOMPARE(wv->property("prefHeight").toInt(), 500);
360}
361
362void tst_QDeclarativeWebView::preferredWidthDefaultTest()
363{
364    QGraphicsWebView view;
365    view.load(QUrl("qrc:///resources/sample.html"));
366
367    QDeclarativeEngine engine;
368    QDeclarativeComponent component(&engine, QUrl("qrc:///resources/webviewtestdefault.qml"));
369    checkNoErrors(component);
370    QObject* wv = component.create();
371    QVERIFY(wv);
372    wv->setProperty("testUrl", QUrl("qrc:///resources/sample.html"));
373    QCOMPARE(wv->property("prefWidth").toDouble(), view.preferredWidth());
374}
375
376void tst_QDeclarativeWebView::preferredHeightDefaultTest()
377{
378    QGraphicsWebView view;
379    view.load(QUrl("qrc:///resources/sample.html"));
380
381    QDeclarativeEngine engine;
382    QDeclarativeComponent component(&engine, QUrl("qrc:///resources/webviewtestdefault.qml"));
383    checkNoErrors(component);
384    QObject* wv = component.create();
385    QVERIFY(wv);
386    wv->setProperty("testUrl", QUrl("qrc:///resources/sample.html"));
387    QCOMPARE(wv->property("prefHeight").toDouble(), view.preferredHeight());
388}
389
390void tst_QDeclarativeWebView::pressGrabTime()
391{
392    QDeclarativeEngine engine;
393    QDeclarativeComponent component(&engine, QUrl("qrc:///resources/propertychanges.qml"));
394    checkNoErrors(component);
395    QDeclarativeItem* rootItem = qobject_cast<QDeclarativeItem*>(component.create());
396    QVERIFY(rootItem);
397    QObject* wv = rootItem->findChild<QObject*>("webView");
398    QVERIFY(wv);
399    QTRY_COMPARE(wv->property("progress").toDouble(), 1.0);
400    QCOMPARE(wv->property("pressGrabTime").toInt(), 200);
401    QSignalSpy pressGrabTimeSpy(wv, SIGNAL(pressGrabTimeChanged()));
402
403    wv->setProperty("pressGrabTime", 100);
404    QCOMPARE(wv->property("pressGrabTime").toInt(), 100);
405    QCOMPARE(pressGrabTimeSpy.count(), 1);
406
407    wv->setProperty("pressGrabTime", 100);
408    QCOMPARE(pressGrabTimeSpy.count(), 1);
409
410    wv->setProperty("pressGrabTime", 0);
411    QCOMPARE(pressGrabTimeSpy.count(), 2);
412}
413
414void tst_QDeclarativeWebView::renderingEnabled()
415{
416    QDeclarativeEngine engine;
417    QDeclarativeComponent component(&engine, QUrl("qrc:///resources/propertychanges.qml"));
418    checkNoErrors(component);
419    QDeclarativeItem* rootItem = qobject_cast<QDeclarativeItem*>(component.create());
420    QVERIFY(rootItem);
421    QObject* wv = rootItem->findChild<QObject*>("webView");
422    QVERIFY(wv);
423    QTRY_COMPARE(wv->property("progress").toDouble(), 1.0);
424
425    QVERIFY(wv->property("renderingEnabled").toBool());
426    QSignalSpy renderingEnabledSpy(wv, SIGNAL(renderingEnabledChanged()));
427
428    wv->setProperty("renderingEnabled", false);
429    QVERIFY(!wv->property("renderingEnabled").toBool());
430    QCOMPARE(renderingEnabledSpy.count(), 1);
431
432    wv->setProperty("renderingEnabled", false);
433    QCOMPARE(renderingEnabledSpy.count(), 1);
434
435    wv->setProperty("renderingEnabled", true);
436    QCOMPARE(renderingEnabledSpy.count(), 2);
437}
438
439void tst_QDeclarativeWebView::setHtml()
440{
441    QDeclarativeEngine engine;
442    QDeclarativeComponent component(&engine, QUrl("qrc:///resources/sethtml.qml"));
443    checkNoErrors(component);
444    QObject* wv = component.create();
445    QVERIFY(wv);
446    QCOMPARE(wv->property("html").toString(), QLatin1String("<html><head></head><body><p>This is a <b>string</b> set on the WebView</p></body></html>"));
447
448    QSignalSpy spy(wv, SIGNAL(htmlChanged()));
449    wv->setProperty("html", QLatin1String("<html><head><title>Basic</title></head><body><p>text</p></body></html>"));
450    QCOMPARE(spy.count(), 1);
451}
452
453void tst_QDeclarativeWebView::settings()
454{
455    QDeclarativeEngine engine;
456    QDeclarativeComponent component(&engine, QUrl("qrc:///resources/basic.qml"));
457    checkNoErrors(component);
458    QObject* wv = component.create();
459    QVERIFY(wv);
460    QTRY_COMPARE(wv->property("progress").toDouble(), 1.0);
461
462    QObject* s = QDeclarativeProperty(wv, "settings").object();
463    QVERIFY(s);
464
465    QStringList settingsList;
466    settingsList << QString::fromAscii("autoLoadImages")
467                 << QString::fromAscii("developerExtrasEnabled")
468                 << QString::fromAscii("javaEnabled")
469                 << QString::fromAscii("javascriptCanAccessClipboard")
470                 << QString::fromAscii("javascriptCanOpenWindows")
471                 << QString::fromAscii("javascriptEnabled")
472                 << QString::fromAscii("linksIncludedInFocusChain")
473                 << QString::fromAscii("localContentCanAccessRemoteUrls")
474                 << QString::fromAscii("localStorageDatabaseEnabled")
475                 << QString::fromAscii("offlineStorageDatabaseEnabled")
476                 << QString::fromAscii("offlineWebApplicationCacheEnabled")
477                 << QString::fromAscii("pluginsEnabled")
478                 << QString::fromAscii("printElementBackgrounds")
479                 << QString::fromAscii("privateBrowsingEnabled")
480                 << QString::fromAscii("zoomTextOnly");
481
482    // Merely tests that setting gets stored (in QWebSettings), behavioural tests are in WebKit.
483    for (int b = 0; b <= 1; b++) {
484        bool value = !!b;
485        foreach (const QString& name, settingsList)
486            s->setProperty(name.toAscii().data(), value);
487        for (int i = 0; i < 2; i++) {
488            foreach (const QString& name, settingsList)
489                QCOMPARE(s->property(name.toAscii().data()).toBool(), value);
490        }
491    }
492}
493
494#if QT_VERSION >= 0x040703
495void tst_QDeclarativeWebView::backgroundColor()
496{
497    // We test here the rendering of the background.
498    QDeclarativeEngine engine;
499    QDeclarativeComponent component(&engine, QUrl("qrc:///resources/webviewbackgroundcolor.qml"));
500    checkNoErrors(component);
501    QObject* wv = component.create();
502    QVERIFY(wv);
503    QCOMPARE(wv->property("backgroundColor").value<QColor>(), QColor(Qt::red));
504    QDeclarativeView view;
505    view.setSource(QUrl("qrc:///resources/webviewbackgroundcolor.qml"));
506    view.show();
507    QTest::qWaitForWindowShown(&view);
508    QPixmap result(view.width(), view.height());
509    QPainter painter(&result);
510    view.render(&painter);
511    QPixmap reference(view.width(), view.height());
512    reference.fill(Qt::red);
513    QCOMPARE(reference, result);
514
515    // We test the emission of the backgroundColorChanged signal.
516    QSignalSpy spyColorChanged(wv, SIGNAL(backgroundColorChanged()));
517    wv->setProperty("backgroundColor", Qt::red);
518    QCOMPARE(spyColorChanged.count(), 0);
519    wv->setProperty("backgroundColor", Qt::green);
520    QCOMPARE(spyColorChanged.count(), 1);
521}
522#endif
523
524void tst_QDeclarativeWebView::checkNoErrors(const QDeclarativeComponent& component)
525{
526    // Wait until the component is ready
527    QTRY_VERIFY(component.isReady() || component.isError());
528    if (component.isError()) {
529        QList<QDeclarativeError> errors = component.errors();
530        for (int ii = 0; ii < errors.count(); ++ii) {
531            const QDeclarativeError &error = errors.at(ii);
532            QByteArray errorStr = QByteArray::number(error.line()) + ":" +
533                                  QByteArray::number(error.column()) + ":" +
534                                  error.description().toUtf8();
535            qWarning() << errorStr;
536        }
537    }
538    QVERIFY(!component.isError());
539}
540
541QTEST_MAIN(tst_QDeclarativeWebView)
542#include "tst_qdeclarativewebview.moc"
543
544QT_END_NAMESPACE
545