From ef0bebc89a4d716d4bd3467bcbc971ca4101d974 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCri=20Valdmann?= <juri.valdmann@qt.io> Date: Thu, 22 Mar 2018 16:19:11 +0100 Subject: [PATCH] Add tst_qwebenginescript loadEvents MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace injectionPoint test with a timeout-less version that uses - both a single-frame and a multi-frame page - both main and isolated worlds - cross-process navigation - window.open - profile-wide scripts Task-number: QTBUG-66338 Change-Id: Ica4acb8ada4acc38aa5e1ca00e7512a2e69b785f Reviewed-by: Michael Brüning <michael.bruning@qt.io> --- .../resources/test_window_open.html | 10 ++ .../qwebenginescript/tst_qwebenginescript.cpp | 143 +++++++++++++----- .../qwebenginescript/tst_qwebenginescript.qrc | 1 + 3 files changed, 115 insertions(+), 39 deletions(-) create mode 100644 tests/auto/widgets/qwebenginescript/resources/test_window_open.html diff --git a/tests/auto/widgets/qwebenginescript/resources/test_window_open.html b/tests/auto/widgets/qwebenginescript/resources/test_window_open.html new file mode 100644 index 000000000..3f72d176d --- /dev/null +++ b/tests/auto/widgets/qwebenginescript/resources/test_window_open.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html> + <head> + <title>window.open</title> + <script> + window.open("qrc:/resource/test_iframe_main.html", "iframe_main"); + </script> + </head> + <body></body> +</html> diff --git a/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp b/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp index e342632e7..882db1a70 100644 --- a/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp +++ b/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp @@ -32,8 +32,7 @@ class tst_QWebEngineScript: public QObject { private Q_SLOTS: void domEditing(); - void injectionPoint(); - void injectionPoint_data(); + void loadEvents(); void scriptWorld(); void scriptModifications(); void webChannel_data(); @@ -75,44 +74,110 @@ void tst_QWebEngineScript::domEditing() QCOMPARE(evaluateJavaScriptSync(&page, "document.elementFromPoint(2, 2).id"), QVariant::fromValue(QStringLiteral("banner"))); } -void tst_QWebEngineScript::injectionPoint() +void tst_QWebEngineScript::loadEvents() { - QFETCH(int, injectionPoint); - QFETCH(QString, testScript); - - QWebEngineScript s; - s.setSourceCode("var foo = \"foobar\";"); - s.setInjectionPoint(static_cast<QWebEngineScript::InjectionPoint>(injectionPoint)); - s.setWorldId(QWebEngineScript::MainWorld); - QWebEnginePage page; - QSignalSpy spyFinished(&page, &QWebEnginePage::loadFinished); - page.scripts().insert(s); - page.setHtml(QStringLiteral("<html><head><script>") + testScript + QStringLiteral("</script></head><body></body></html>")); - QVERIFY(spyFinished.wait()); - const QVariant expected(QVariant::fromValue(QStringLiteral("SUCCESS"))); - QTRY_COMPARE(evaluateJavaScriptSync(&page, "document.myContents"), expected); -} - -void tst_QWebEngineScript::injectionPoint_data() -{ - QTest::addColumn<int>("injectionPoint"); - QTest::addColumn<QString>("testScript"); - QTest::newRow("DocumentCreation") << static_cast<int>(QWebEngineScript::DocumentCreation) - << QStringLiteral("document.myContents = (typeof(foo) == \"undefined\")? \"FAILURE\" : \"SUCCESS\";"); - QTest::newRow("DocumentReady") << static_cast<int>(QWebEngineScript::DocumentReady) - // use a zero timeout to make sure the user script got a chance to run as the order is undefined. - << QStringLiteral("document.addEventListener(\"DOMContentLoaded\", function() {\ - setTimeout(function() {\ - document.myContents = (typeof(foo) == \"undefined\")? \"FAILURE\" : \"SUCCESS\";\ - }, 0)});"); - QTest::newRow("Deferred") << static_cast<int>(QWebEngineScript::DocumentReady) - << QStringLiteral("document.onreadystatechange = function() { \ - if (document.readyState == \"complete\") { \ - setTimeout(function() {\ - document.myContents = (typeof(foo) == \"undefined\")? \"FAILURE\" : \"SUCCESS\";\ - }, 0);\ - } \ - };"); + // Test relative order of injection and loading. + // + // - install event listeners for "DOMContentLoaded" and "load" events + // - install user scripts for every injection point + // - check that event listeners and user scripts execute in the expected order + + class Page; + class Profile : public QWebEngineProfile { + QWebEngineScript scriptFor(QWebEngineScript::ScriptWorldId worldId, + QWebEngineScript::InjectionPoint injectionPoint) { + QWebEngineScript script; + script.setWorldId(worldId); + script.setInjectionPoint(injectionPoint); + script.setRunsOnSubFrames(true); + if (injectionPoint == QWebEngineScript::DocumentCreation) { + script.setSourceCode(QStringLiteral(R"( + var log = ["DocumentCreation"]; + for (let type of ["DOMContentLoaded", "load"]) { + window.addEventListener(type, () => log.push(type)); + } + )")); + } else if (injectionPoint == QWebEngineScript::DocumentReady) { + script.setSourceCode(QStringLiteral(R"(log.push("DocumentReady"))")); + } else { + script.setSourceCode(QStringLiteral(R"(log.push("Deferred"))")); + } + return script; + } + public: + Profile() { + scripts()->insert(scriptFor(QWebEngineScript::MainWorld, QWebEngineScript::DocumentCreation)); + scripts()->insert(scriptFor(QWebEngineScript::MainWorld, QWebEngineScript::DocumentReady)); + scripts()->insert(scriptFor(QWebEngineScript::MainWorld, QWebEngineScript::Deferred)); + scripts()->insert(scriptFor(QWebEngineScript::ApplicationWorld, QWebEngineScript::DocumentCreation)); + scripts()->insert(scriptFor(QWebEngineScript::ApplicationWorld, QWebEngineScript::DocumentReady)); + scripts()->insert(scriptFor(QWebEngineScript::ApplicationWorld, QWebEngineScript::Deferred)); + } + std::list<Page> pages; + }; + + class Page : public QWebEnginePage { + QWebEnginePage *createWindow(WebWindowType) override { + profile.pages.emplace_back(profile); + return &profile.pages.back(); + }; + public: + Page(Profile &profile) : QWebEnginePage(&profile), profile(profile) {} + QVariant eval(const QString &code, QWebEngineScript::ScriptWorldId worldId) + { + return evaluateJavaScriptSyncInWorld(this, code, worldId); + } + Profile &profile; + QSignalSpy spy{this, &QWebEnginePage::loadFinished}; + }; + + Profile profile; + profile.pages.emplace_back(profile); + Page &page = profile.pages.back(); + + const QStringList expected = { + "DocumentCreation", + "DOMContentLoaded", + "DocumentReady", + "load", + "Deferred" + }; + + // Single frame / setHtml + page.setHtml(QStringLiteral("<!DOCTYPE html><html><head><title>mr</title></head><body></body></html>")); + QTRY_COMPARE(page.spy.count(), 1); + QCOMPARE(page.spy.takeFirst().value(0).toBool(), true); + QCOMPARE(page.eval("window.log", QWebEngineScript::MainWorld).toStringList(), expected); + QCOMPARE(page.eval("window.log", QWebEngineScript::ApplicationWorld).toStringList(), expected); + + // Multiple frames + page.load(QUrl("qrc:/resources/test_iframe_main.html")); + QTRY_COMPARE(page.spy.count(), 1); + QCOMPARE(page.spy.takeFirst().value(0).toBool(), true); + QCOMPARE(page.eval("window.log", QWebEngineScript::MainWorld).toStringList(), expected); + QCOMPARE(page.eval("window.log", QWebEngineScript::ApplicationWorld).toStringList(), expected); + QCOMPARE(page.eval("window[0].log", QWebEngineScript::MainWorld).toStringList(), expected); + QCOMPARE(page.eval("window[0].log", QWebEngineScript::ApplicationWorld).toStringList(), expected); + QCOMPARE(page.eval("window[0][0].log", QWebEngineScript::MainWorld).toStringList(), expected); + QCOMPARE(page.eval("window[0][0].log", QWebEngineScript::ApplicationWorld).toStringList(), expected); + + // Cross-process navigation + page.load(QUrl("chrome://gpu")); + QTRY_COMPARE(page.spy.count(), 1); + QCOMPARE(page.spy.takeFirst().value(0).toBool(), true); + QCOMPARE(page.eval("window.log", QWebEngineScript::MainWorld).toStringList(), expected); + QCOMPARE(page.eval("window.log", QWebEngineScript::ApplicationWorld).toStringList(), expected); + + // Using window.open from JS + QCOMPARE(profile.pages.size(), 1u); + page.load(QUrl("qrc:/resources/test_window_open.html")); + QTRY_COMPARE(profile.pages.size(), 2u); + QTRY_COMPARE(profile.pages.front().spy.count(), 1); + QTRY_COMPARE(profile.pages.back().spy.count(), 1); + QCOMPARE(profile.pages.front().eval("window.log", QWebEngineScript::MainWorld).toStringList(), expected); + QCOMPARE(profile.pages.front().eval("window.log", QWebEngineScript::ApplicationWorld).toStringList(), expected); + QCOMPARE(profile.pages.back().eval("window.log", QWebEngineScript::MainWorld).toStringList(), expected); + QCOMPARE(profile.pages.back().eval("window.log", QWebEngineScript::ApplicationWorld).toStringList(), expected); } void tst_QWebEngineScript::scriptWorld() diff --git a/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.qrc b/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.qrc index 8b7a11cf2..9960a37ba 100644 --- a/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.qrc +++ b/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.qrc @@ -3,5 +3,6 @@ <file>resources/test_iframe_main.html</file> <file>resources/test_iframe_outer.html</file> <file>resources/test_iframe_inner.html</file> + <file>resources/test_window_open.html</file> </qresource> </RCC> -- GitLab