1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
43 #include <QDeclarativeEngine>
44 #include <QDeclarativeComponent>
46 #include <QNetworkCookieJar>
47 #include "testhttpserver.h"
48 #include "../../../shared/util.h"
50 #define SERVER_PORT 14445
53 // In Symbian OS test data is located in applications private dir
57 class tst_qdeclarativexmlhttprequest : public QObject
61 tst_qdeclarativexmlhttprequest() {}
64 void domExceptionCodes();
65 void callbackException();
66 void callbackException_data();
67 void staticStateValues();
68 void instanceStateValues();
73 void open_invalid_method();
75 void open_arg_count();
76 void setRequestHeader();
77 void setRequestHeader_unsent();
78 void setRequestHeader_illegalName_data();
79 void setRequestHeader_illegalName();
80 void setRequestHeader_sent();
81 void setRequestHeader_args();
83 void send_alreadySent();
84 void send_ignoreData();
86 void send_withdata_data();
90 void getResponseHeader();
91 void getResponseHeader_unsent();
92 void getResponseHeader_sent();
93 void getResponseHeader_args();
94 void getAllResponseHeaders();
95 void getAllResponseHeaders_unsent();
96 void getAllResponseHeaders_sent();
97 void getAllResponseHeaders_args();
101 void statusText_data();
103 void responseText_data();
104 void responseXML_invalid();
105 void invalidMethodUsage();
118 // void outstanding_request_at_shutdown();
120 // void network_errors()
124 QDeclarativeEngine engine;
127 inline QUrl TEST_FILE(const QString &filename)
129 return QUrl::fromLocalFile(QLatin1String(SRCDIR) + QLatin1String("/data/") + filename);
132 // Test that the dom exception codes are correct
133 void tst_qdeclarativexmlhttprequest::domExceptionCodes()
135 QDeclarativeComponent component(&engine, TEST_FILE("domExceptionCodes.qml"));
136 QObject *object = component.create();
137 QVERIFY(object != 0);
139 QCOMPARE(object->property("index_size_err").toInt(), 1);
140 QCOMPARE(object->property("domstring_size_err").toInt(), 2);
141 QCOMPARE(object->property("hierarchy_request_err").toInt(), 3);
142 QCOMPARE(object->property("wrong_document_err").toInt(), 4);
143 QCOMPARE(object->property("invalid_character_err").toInt(), 5);
144 QCOMPARE(object->property("no_data_allowed_err").toInt(), 6);
145 QCOMPARE(object->property("no_modification_allowed_err").toInt(), 7);
146 QCOMPARE(object->property("not_found_err").toInt(), 8);
147 QCOMPARE(object->property("not_supported_err").toInt(), 9);
148 QCOMPARE(object->property("inuse_attribute_err").toInt(), 10);
149 QCOMPARE(object->property("invalid_state_err").toInt(), 11);
150 QCOMPARE(object->property("syntax_err").toInt(), 12);
151 QCOMPARE(object->property("invalid_modification_err").toInt(), 13);
152 QCOMPARE(object->property("namespace_err").toInt(), 14);
153 QCOMPARE(object->property("invalid_access_err").toInt(), 15);
154 QCOMPARE(object->property("validation_err").toInt(), 16);
155 QCOMPARE(object->property("type_mismatch_err").toInt(), 17);
160 void tst_qdeclarativexmlhttprequest::callbackException_data()
162 QTest::addColumn<QString>("which");
163 QTest::addColumn<int>("line");
165 QTest::newRow("on-opened") << "1" << 15;
166 QTest::newRow("on-loading") << "3" << 15;
167 QTest::newRow("on-done") << "4" << 15;
170 void tst_qdeclarativexmlhttprequest::callbackException()
172 // Test exception reporting for exceptions thrown at various points.
174 QFETCH(QString, which);
177 QString expect = TEST_FILE("callbackException.qml").toString() + ":"+QString::number(line)+": Error: Exception from Callback";
178 QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
180 QDeclarativeComponent component(&engine, TEST_FILE("callbackException.qml"));
181 QObject *object = component.beginCreate(engine.rootContext());
182 QVERIFY(object != 0);
183 object->setProperty("url", "testdocument.html");
184 object->setProperty("which", which);
185 component.completeCreate();
187 QTRY_VERIFY(object->property("threw").toBool() == true);
192 // Test that the state value properties on the XMLHttpRequest constructor have the correct values.
193 // ### WebKit does not do this, but it seems to fit the standard and QML better
194 void tst_qdeclarativexmlhttprequest::staticStateValues()
196 QDeclarativeComponent component(&engine, TEST_FILE("staticStateValues.qml"));
197 QObject *object = component.create();
198 QVERIFY(object != 0);
200 QCOMPARE(object->property("unsent").toInt(), 0);
201 QCOMPARE(object->property("opened").toInt(), 1);
202 QCOMPARE(object->property("headers_received").toInt(), 2);
203 QCOMPARE(object->property("loading").toInt(), 3);
204 QCOMPARE(object->property("done").toInt(), 4);
209 // Test that the state value properties on instances have the correct values.
210 void tst_qdeclarativexmlhttprequest::instanceStateValues()
212 QDeclarativeComponent component(&engine, TEST_FILE("instanceStateValues.qml"));
213 QObject *object = component.create();
214 QVERIFY(object != 0);
216 QCOMPARE(object->property("unsent").toInt(), 0);
217 QCOMPARE(object->property("opened").toInt(), 1);
218 QCOMPARE(object->property("headers_received").toInt(), 2);
219 QCOMPARE(object->property("loading").toInt(), 3);
220 QCOMPARE(object->property("done").toInt(), 4);
225 // Test calling constructor
226 void tst_qdeclarativexmlhttprequest::constructor()
228 QDeclarativeComponent component(&engine, TEST_FILE("constructor.qml"));
229 QObject *object = component.create();
230 QVERIFY(object != 0);
232 QCOMPARE(object->property("calledAsConstructor").toBool(), true);
233 QCOMPARE(object->property("calledAsFunction").toBool(), true);
238 // Test that all the properties are set correctly before any request is sent
239 void tst_qdeclarativexmlhttprequest::defaultState()
241 QDeclarativeComponent component(&engine, TEST_FILE("defaultState.qml"));
242 QObject *object = component.create();
243 QVERIFY(object != 0);
245 QCOMPARE(object->property("readState").toInt(), 0);
246 QCOMPARE(object->property("statusIsException").toBool(), true);
247 QCOMPARE(object->property("statusTextIsException").toBool(), true);
248 QCOMPARE(object->property("responseText").toString(), QString());
249 QCOMPARE(object->property("responseXMLIsNull").toBool(), true);
254 // Test valid XMLHttpRequest.open() calls
255 void tst_qdeclarativexmlhttprequest::open()
257 QFETCH(QUrl, qmlFile);
258 QFETCH(QString, url);
259 QFETCH(bool, remote);
261 TestHTTPServer *server = 0;
263 server = new TestHTTPServer(SERVER_PORT);
264 QVERIFY(server->isValid());
265 QVERIFY(server->wait(TEST_FILE("open_network.expect"),
266 TEST_FILE("open_network.reply"),
267 TEST_FILE("testdocument.html")));
270 QDeclarativeComponent component(&engine, qmlFile);
271 QObject *object = component.beginCreate(engine.rootContext());
272 QVERIFY(object != 0);
273 object->setProperty("url", url);
274 component.completeCreate();
276 QCOMPARE(object->property("readyState").toBool(), true);
277 QCOMPARE(object->property("openedState").toBool(), true);
278 QCOMPARE(object->property("status").toBool(), true);
279 QCOMPARE(object->property("statusText").toBool(), true);
280 QCOMPARE(object->property("responseText").toBool(), true);
281 QCOMPARE(object->property("responseXML").toBool(), true);
283 QTRY_VERIFY(object->property("dataOK").toBool() == true);
289 void tst_qdeclarativexmlhttprequest::open_data()
291 QTest::addColumn<QUrl>("qmlFile");
292 QTest::addColumn<QString>("url");
293 QTest::addColumn<bool>("remote");
295 QTest::newRow("Relative url)") << TEST_FILE("open.qml") << "testdocument.html" << false;
296 QTest::newRow("Absolute url)") << TEST_FILE("open.qml") << TEST_FILE("testdocument.html").toString() << false;
297 QTest::newRow("Absolute network url)") << TEST_FILE("open.qml") << "http://127.0.0.1:14445/testdocument.html" << true;
299 // ### Check that the username/password were sent to the server
300 QTest::newRow("User/pass") << TEST_FILE("open_user.qml") << "http://127.0.0.1:14445/testdocument.html" << true;
303 // Test that calling XMLHttpRequest.open() with an invalid method raises an exception
304 void tst_qdeclarativexmlhttprequest::open_invalid_method()
306 QDeclarativeComponent component(&engine, TEST_FILE("open_invalid_method.qml"));
307 QObject *object = component.create();
308 QVERIFY(object != 0);
310 QCOMPARE(object->property("exceptionThrown").toBool(), true);
315 // Test that calling XMLHttpRequest.open() with sync raises an exception
316 void tst_qdeclarativexmlhttprequest::open_sync()
318 QDeclarativeComponent component(&engine, TEST_FILE("open_sync.qml"));
319 QObject *object = component.create();
320 QVERIFY(object != 0);
322 QCOMPARE(object->property("exceptionThrown").toBool(), true);
327 // Calling with incorrect arg count raises an exception
328 void tst_qdeclarativexmlhttprequest::open_arg_count()
331 QDeclarativeComponent component(&engine, TEST_FILE("open_arg_count.1.qml"));
332 QObject *object = component.create();
333 QVERIFY(object != 0);
335 QCOMPARE(object->property("exceptionThrown").toBool(), true);
341 QDeclarativeComponent component(&engine, TEST_FILE("open_arg_count.2.qml"));
342 QObject *object = component.create();
343 QVERIFY(object != 0);
345 QCOMPARE(object->property("exceptionThrown").toBool(), true);
351 // Test valid setRequestHeader() calls
352 void tst_qdeclarativexmlhttprequest::setRequestHeader()
354 TestHTTPServer server(SERVER_PORT);
355 QVERIFY(server.isValid());
356 QVERIFY(server.wait(TEST_FILE("setRequestHeader.expect"),
357 TEST_FILE("setRequestHeader.reply"),
358 TEST_FILE("testdocument.html")));
360 QDeclarativeComponent component(&engine, TEST_FILE("setRequestHeader.qml"));
361 QObject *object = component.beginCreate(engine.rootContext());
362 QVERIFY(object != 0);
363 object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
364 component.completeCreate();
366 QTRY_VERIFY(object->property("dataOK").toBool() == true);
371 // Test setting headers before open() throws exception
372 void tst_qdeclarativexmlhttprequest::setRequestHeader_unsent()
374 QDeclarativeComponent component(&engine, TEST_FILE("setRequestHeader_unsent.qml"));
375 QObject *object = component.create();
376 QVERIFY(object != 0);
378 QCOMPARE(object->property("test").toBool(), true);
383 void tst_qdeclarativexmlhttprequest::setRequestHeader_illegalName_data()
385 QTest::addColumn<QString>("name");
387 QTest::newRow("Accept-Charset") << "AccePT-CHArset";
388 QTest::newRow("Accept-Encoding") << "AccEpt-EnCOding";
389 QTest::newRow("Connection") << "ConnECtion";
390 QTest::newRow("Content-Length") << "ContEnt-LenGth";
391 QTest::newRow("Cookie") << "CookIe";
392 QTest::newRow("Cookie2") << "CoOkie2";
393 QTest::newRow("Content-Transfer-Encoding") << "ConteNT-tRANSFER-eNCOding";
394 QTest::newRow("Date") << "DaTE";
395 QTest::newRow("Expect") << "ExPect";
396 QTest::newRow("Host") << "HoST";
397 QTest::newRow("Keep-Alive") << "KEEP-aLive";
398 QTest::newRow("Referer") << "ReferEr";
399 QTest::newRow("TE") << "Te";
400 QTest::newRow("Trailer") << "TraILEr";
401 QTest::newRow("Transfer-Encoding") << "tRANsfer-Encoding";
402 QTest::newRow("Upgrade") << "UpgrADe";
403 QTest::newRow("User-Agent") << "uSEr-Agent";
404 QTest::newRow("Via") << "vIa";
405 QTest::newRow("Proxy-") << "ProXy-";
406 QTest::newRow("Sec-") << "SeC-";
407 QTest::newRow("Proxy-*") << "Proxy-BLAH";
408 QTest::newRow("Sec-*") << "Sec-F";
411 // Tests that using illegal header names has no effect
412 void tst_qdeclarativexmlhttprequest::setRequestHeader_illegalName()
414 QFETCH(QString, name);
416 TestHTTPServer server(SERVER_PORT);
417 QVERIFY(server.isValid());
418 QVERIFY(server.wait(TEST_FILE("open_network.expect"),
419 TEST_FILE("open_network.reply"),
420 TEST_FILE("testdocument.html")));
422 QDeclarativeComponent component(&engine, TEST_FILE("setRequestHeader_illegalName.qml"));
423 QObject *object = component.beginCreate(engine.rootContext());
424 QVERIFY(object != 0);
425 object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
426 object->setProperty("header", name);
427 component.completeCreate();
429 QCOMPARE(object->property("readyState").toBool(), true);
430 QCOMPARE(object->property("openedState").toBool(), true);
431 QCOMPARE(object->property("status").toBool(), true);
432 QCOMPARE(object->property("statusText").toBool(), true);
433 QCOMPARE(object->property("responseText").toBool(), true);
434 QCOMPARE(object->property("responseXML").toBool(), true);
436 QTRY_VERIFY(object->property("dataOK").toBool() == true);
441 // Test that attempting to set a header after a request is sent throws an exception
442 void tst_qdeclarativexmlhttprequest::setRequestHeader_sent()
444 TestHTTPServer server(SERVER_PORT);
445 QVERIFY(server.isValid());
446 QVERIFY(server.wait(TEST_FILE("open_network.expect"),
447 TEST_FILE("open_network.reply"),
448 TEST_FILE("testdocument.html")));
450 QDeclarativeComponent component(&engine, TEST_FILE("setRequestHeader_sent.qml"));
451 QObject *object = component.beginCreate(engine.rootContext());
452 QVERIFY(object != 0);
453 object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
454 component.completeCreate();
456 QCOMPARE(object->property("test").toBool(), true);
458 QTRY_VERIFY(object->property("dataOK").toBool() == true);
463 // Invalid arg count throws exception
464 void tst_qdeclarativexmlhttprequest::setRequestHeader_args()
466 QDeclarativeComponent component(&engine, TEST_FILE("setRequestHeader_args.qml"));
467 QObject *object = component.create();
468 QVERIFY(object != 0);
470 QCOMPARE(object->property("exceptionThrown").toBool(), true);
475 // Test that calling send() in UNSENT state throws an exception
476 void tst_qdeclarativexmlhttprequest::send_unsent()
478 QDeclarativeComponent component(&engine, TEST_FILE("send_unsent.qml"));
479 QObject *object = component.create();
480 QVERIFY(object != 0);
482 QCOMPARE(object->property("test").toBool(), true);
487 // Test attempting to resend a sent request throws an exception
488 void tst_qdeclarativexmlhttprequest::send_alreadySent()
490 QDeclarativeComponent component(&engine, TEST_FILE("send_alreadySent.qml"));
491 QObject *object = component.create();
492 QVERIFY(object != 0);
494 QCOMPARE(object->property("test").toBool(), true);
495 QTRY_VERIFY(object->property("dataOK").toBool() == true);
500 // Test that sends for GET, HEAD and DELETE ignore data
501 void tst_qdeclarativexmlhttprequest::send_ignoreData()
504 TestHTTPServer server(SERVER_PORT);
505 QVERIFY(server.isValid());
506 QVERIFY(server.wait(TEST_FILE("send_ignoreData_GET.expect"),
507 TEST_FILE("send_ignoreData.reply"),
508 TEST_FILE("testdocument.html")));
510 QDeclarativeComponent component(&engine, TEST_FILE("send_ignoreData.qml"));
511 QObject *object = component.beginCreate(engine.rootContext());
512 QVERIFY(object != 0);
513 object->setProperty("reqType", "GET");
514 object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
515 component.completeCreate();
517 QTRY_VERIFY(object->property("dataOK").toBool() == true);
523 TestHTTPServer server(SERVER_PORT);
524 QVERIFY(server.isValid());
525 QVERIFY(server.wait(TEST_FILE("send_ignoreData_HEAD.expect"),
526 TEST_FILE("send_ignoreData.reply"),
529 QDeclarativeComponent component(&engine, TEST_FILE("send_ignoreData.qml"));
530 QObject *object = component.beginCreate(engine.rootContext());
531 QVERIFY(object != 0);
532 object->setProperty("reqType", "HEAD");
533 object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
534 component.completeCreate();
536 QTRY_VERIFY(object->property("dataOK").toBool() == true);
542 TestHTTPServer server(SERVER_PORT);
543 QVERIFY(server.isValid());
544 QVERIFY(server.wait(TEST_FILE("send_ignoreData_DELETE.expect"),
545 TEST_FILE("send_ignoreData.reply"),
548 QDeclarativeComponent component(&engine, TEST_FILE("send_ignoreData.qml"));
549 QObject *object = component.beginCreate(engine.rootContext());
550 QVERIFY(object != 0);
551 object->setProperty("reqType", "DELETE");
552 object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
553 component.completeCreate();
555 QTRY_VERIFY(object->property("dataOK").toBool() == true);
561 // Test that send()'ing data works
562 void tst_qdeclarativexmlhttprequest::send_withdata()
564 QFETCH(QString, file_expected);
565 QFETCH(QString, file_qml);
567 TestHTTPServer server(SERVER_PORT);
568 QVERIFY(server.isValid());
569 QVERIFY(server.wait(TEST_FILE(file_expected),
570 TEST_FILE("send_data.reply"),
571 TEST_FILE("testdocument.html")));
573 QDeclarativeComponent component(&engine, TEST_FILE(file_qml));
574 QObject *object = component.beginCreate(engine.rootContext());
575 QVERIFY(object != 0);
576 object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
577 component.completeCreate();
579 QTRY_VERIFY(object->property("dataOK").toBool() == true);
584 void tst_qdeclarativexmlhttprequest::send_withdata_data()
586 QTest::addColumn<QString>("file_expected");
587 QTest::addColumn<QString>("file_qml");
589 QTest::newRow("No content-type") << "send_data.1.expect" << "send_data.1.qml";
590 QTest::newRow("Correct content-type") << "send_data.1.expect" << "send_data.2.qml";
591 QTest::newRow("Incorrect content-type") << "send_data.1.expect" << "send_data.3.qml";
592 QTest::newRow("Correct content-type - out of order") << "send_data.4.expect" << "send_data.4.qml";
593 QTest::newRow("Incorrect content-type - out of order") << "send_data.4.expect" << "send_data.5.qml";
594 QTest::newRow("PUT") << "send_data.6.expect" << "send_data.6.qml";
595 QTest::newRow("Correct content-type - no charset") << "send_data.1.expect" << "send_data.7.qml";
598 // Test abort() has no effect in unsent state
599 void tst_qdeclarativexmlhttprequest::abort_unsent()
601 QDeclarativeComponent component(&engine, TEST_FILE("abort_unsent.qml"));
602 QObject *object = component.beginCreate(engine.rootContext());
603 QVERIFY(object != 0);
604 object->setProperty("url", "testdocument.html");
605 component.completeCreate();
607 QCOMPARE(object->property("readyState").toBool(), true);
608 QCOMPARE(object->property("openedState").toBool(), true);
609 QCOMPARE(object->property("status").toBool(), true);
610 QCOMPARE(object->property("statusText").toBool(), true);
611 QCOMPARE(object->property("responseText").toBool(), true);
612 QCOMPARE(object->property("responseXML").toBool(), true);
614 QTRY_VERIFY(object->property("dataOK").toBool() == true);
619 // Test abort() cancels an open (but unsent) request
620 void tst_qdeclarativexmlhttprequest::abort_opened()
622 QDeclarativeComponent component(&engine, TEST_FILE("abort_opened.qml"));
623 QObject *object = component.beginCreate(engine.rootContext());
624 QVERIFY(object != 0);
625 object->setProperty("url", "testdocument.html");
626 component.completeCreate();
628 QCOMPARE(object->property("readyState").toBool(), true);
629 QCOMPARE(object->property("openedState").toBool(), true);
630 QCOMPARE(object->property("status").toBool(), true);
631 QCOMPARE(object->property("statusText").toBool(), true);
632 QCOMPARE(object->property("responseText").toBool(), true);
633 QCOMPARE(object->property("responseXML").toBool(), true);
635 QTRY_VERIFY(object->property("dataOK").toBool() == true);
640 // Test abort() aborts in progress send
641 void tst_qdeclarativexmlhttprequest::abort()
643 TestHTTPServer server(SERVER_PORT);
644 QVERIFY(server.isValid());
645 QVERIFY(server.wait(TEST_FILE("abort.expect"),
646 TEST_FILE("abort.reply"),
647 TEST_FILE("testdocument.html")));
649 QDeclarativeComponent component(&engine, TEST_FILE("abort.qml"));
650 QObject *object = component.beginCreate(engine.rootContext());
651 QVERIFY(object != 0);
652 object->setProperty("urlDummy", "http://127.0.0.1:14449/testdocument.html");
653 object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
654 component.completeCreate();
656 QCOMPARE(object->property("seenDone").toBool(), true);
657 QCOMPARE(object->property("didNotSeeUnsent").toBool(), true);
658 QCOMPARE(object->property("endStateUnsent").toBool(), true);
660 QTRY_VERIFY(object->property("dataOK").toBool() == true);
665 void tst_qdeclarativexmlhttprequest::getResponseHeader()
667 QDeclarativeEngine engine; // Avoid cookie contamination
669 TestHTTPServer server(SERVER_PORT);
670 QVERIFY(server.isValid());
671 QVERIFY(server.wait(TEST_FILE("getResponseHeader.expect"),
672 TEST_FILE("getResponseHeader.reply"),
673 TEST_FILE("testdocument.html")));
676 QDeclarativeComponent component(&engine, TEST_FILE("getResponseHeader.qml"));
677 QObject *object = component.beginCreate(engine.rootContext());
678 QVERIFY(object != 0);
679 object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
680 component.completeCreate();
682 QCOMPARE(object->property("unsentException").toBool(), true);
683 QCOMPARE(object->property("openedException").toBool(), true);
684 QCOMPARE(object->property("readyState").toBool(), true);
685 QCOMPARE(object->property("openedState").toBool(), true);
687 QTRY_VERIFY(object->property("dataOK").toBool() == true);
689 QCOMPARE(object->property("headersReceivedState").toBool(), true);
690 QCOMPARE(object->property("headersReceivedNullHeader").toBool(), true);
691 QCOMPARE(object->property("headersReceivedValidHeader").toBool(), true);
692 QCOMPARE(object->property("headersReceivedMultiValidHeader").toBool(), true);
693 QCOMPARE(object->property("headersReceivedCookieHeader").toBool(), true);
695 QCOMPARE(object->property("doneState").toBool(), true);
696 QCOMPARE(object->property("doneNullHeader").toBool(), true);
697 QCOMPARE(object->property("doneValidHeader").toBool(), true);
698 QCOMPARE(object->property("doneMultiValidHeader").toBool(), true);
699 QCOMPARE(object->property("doneCookieHeader").toBool(), true);
704 // Test getResponseHeader throws an exception in an invalid state
705 void tst_qdeclarativexmlhttprequest::getResponseHeader_unsent()
707 QDeclarativeComponent component(&engine, TEST_FILE("getResponseHeader_unsent.qml"));
708 QObject *object = component.create();
709 QVERIFY(object != 0);
711 QCOMPARE(object->property("test").toBool(), true);
716 // Test getResponseHeader throws an exception in an invalid state
717 void tst_qdeclarativexmlhttprequest::getResponseHeader_sent()
719 QDeclarativeComponent component(&engine, TEST_FILE("getResponseHeader_sent.qml"));
720 QObject *object = component.create();
721 QVERIFY(object != 0);
723 QCOMPARE(object->property("test").toBool(), true);
728 // Invalid arg count throws exception
729 void tst_qdeclarativexmlhttprequest::getResponseHeader_args()
731 QDeclarativeComponent component(&engine, TEST_FILE("getResponseHeader_args.qml"));
732 QObject *object = component.create();
733 QVERIFY(object != 0);
735 QTRY_VERIFY(object->property("exceptionThrown").toBool() == true);
740 void tst_qdeclarativexmlhttprequest::getAllResponseHeaders()
742 QDeclarativeEngine engine; // Avoid cookie contamination
744 TestHTTPServer server(SERVER_PORT);
745 QVERIFY(server.isValid());
746 QVERIFY(server.wait(TEST_FILE("getResponseHeader.expect"),
747 TEST_FILE("getResponseHeader.reply"),
748 TEST_FILE("testdocument.html")));
750 QDeclarativeComponent component(&engine, TEST_FILE("getAllResponseHeaders.qml"));
751 QObject *object = component.beginCreate(engine.rootContext());
752 QVERIFY(object != 0);
753 object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
754 component.completeCreate();
756 QCOMPARE(object->property("unsentException").toBool(), true);
757 QCOMPARE(object->property("openedException").toBool(), true);
758 QCOMPARE(object->property("readyState").toBool(), true);
759 QCOMPARE(object->property("openedState").toBool(), true);
761 QTRY_VERIFY(object->property("dataOK").toBool() == true);
763 QCOMPARE(object->property("headersReceivedState").toBool(), true);
764 QCOMPARE(object->property("headersReceivedHeader").toBool(), true);
766 QCOMPARE(object->property("doneState").toBool(), true);
767 QCOMPARE(object->property("doneHeader").toBool(), true);
772 // Test getAllResponseHeaders throws an exception in an invalid state
773 void tst_qdeclarativexmlhttprequest::getAllResponseHeaders_unsent()
775 QDeclarativeComponent component(&engine, TEST_FILE("getAllResponseHeaders_unsent.qml"));
776 QObject *object = component.create();
777 QVERIFY(object != 0);
779 QCOMPARE(object->property("test").toBool(), true);
784 // Test getAllResponseHeaders throws an exception in an invalid state
785 void tst_qdeclarativexmlhttprequest::getAllResponseHeaders_sent()
787 QDeclarativeComponent component(&engine, TEST_FILE("getAllResponseHeaders_sent.qml"));
788 QObject *object = component.create();
789 QVERIFY(object != 0);
791 QCOMPARE(object->property("test").toBool(), true);
796 // Invalid arg count throws exception
797 void tst_qdeclarativexmlhttprequest::getAllResponseHeaders_args()
799 QDeclarativeComponent component(&engine, TEST_FILE("getAllResponseHeaders_args.qml"));
800 QObject *object = component.create();
801 QVERIFY(object != 0);
803 QTRY_VERIFY(object->property("exceptionThrown").toBool() == true);
808 void tst_qdeclarativexmlhttprequest::status()
810 QFETCH(QUrl, replyUrl);
813 TestHTTPServer server(SERVER_PORT);
814 QVERIFY(server.isValid());
815 QVERIFY(server.wait(TEST_FILE("status.expect"),
817 TEST_FILE("testdocument.html")));
819 QDeclarativeComponent component(&engine, TEST_FILE("status.qml"));
820 QObject *object = component.beginCreate(engine.rootContext());
821 QVERIFY(object != 0);
822 object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
823 object->setProperty("expectedStatus", status);
824 component.completeCreate();
826 QTRY_VERIFY(object->property("dataOK").toBool() == true);
828 QCOMPARE(object->property("unsentException").toBool(), true);
829 QCOMPARE(object->property("openedException").toBool(), true);
830 QCOMPARE(object->property("sentException").toBool(), true);
831 QCOMPARE(object->property("headersReceived").toBool(), true);
832 QCOMPARE(object->property("loading").toBool(), true);
833 QCOMPARE(object->property("done").toBool(), true);
834 QCOMPARE(object->property("resetException").toBool(), true);
839 void tst_qdeclarativexmlhttprequest::status_data()
841 QTest::addColumn<QUrl>("replyUrl");
842 QTest::addColumn<int>("status");
844 QTest::newRow("OK") << TEST_FILE("status.200.reply") << 200;
845 QTest::newRow("Not Found") << TEST_FILE("status.404.reply") << 404;
848 void tst_qdeclarativexmlhttprequest::statusText()
850 QFETCH(QUrl, replyUrl);
851 QFETCH(QString, statusText);
853 TestHTTPServer server(SERVER_PORT);
854 QVERIFY(server.isValid());
855 QVERIFY(server.wait(TEST_FILE("status.expect"),
857 TEST_FILE("testdocument.html")));
859 QDeclarativeComponent component(&engine, TEST_FILE("statusText.qml"));
860 QObject *object = component.beginCreate(engine.rootContext());
861 QVERIFY(object != 0);
862 object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
863 object->setProperty("expectedStatus", statusText);
864 component.completeCreate();
866 QTRY_VERIFY(object->property("dataOK").toBool() == true);
868 QCOMPARE(object->property("unsentException").toBool(), true);
869 QCOMPARE(object->property("openedException").toBool(), true);
870 QCOMPARE(object->property("sentException").toBool(), true);
871 QCOMPARE(object->property("headersReceived").toBool(), true);
872 QCOMPARE(object->property("loading").toBool(), true);
873 QCOMPARE(object->property("done").toBool(), true);
874 QCOMPARE(object->property("resetException").toBool(), true);
879 void tst_qdeclarativexmlhttprequest::statusText_data()
881 QTest::addColumn<QUrl>("replyUrl");
882 QTest::addColumn<QString>("statusText");
884 QTest::newRow("OK") << TEST_FILE("status.200.reply") << "OK";
885 QTest::newRow("Not Found") << TEST_FILE("status.404.reply") << "Document not found";
888 void tst_qdeclarativexmlhttprequest::responseText()
890 QFETCH(QUrl, replyUrl);
891 QFETCH(QUrl, bodyUrl);
892 QFETCH(QString, responseText);
894 TestHTTPServer server(SERVER_PORT);
895 QVERIFY(server.isValid());
896 QVERIFY(server.wait(TEST_FILE("status.expect"),
900 QDeclarativeComponent component(&engine, TEST_FILE("responseText.qml"));
901 QObject *object = component.beginCreate(engine.rootContext());
902 QVERIFY(object != 0);
903 object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
904 object->setProperty("expectedText", responseText);
905 component.completeCreate();
907 QTRY_VERIFY(object->property("dataOK").toBool() == true);
909 QCOMPARE(object->property("unsent").toBool(), true);
910 QCOMPARE(object->property("opened").toBool(), true);
911 QCOMPARE(object->property("sent").toBool(), true);
912 QCOMPARE(object->property("headersReceived").toBool(), true);
913 QCOMPARE(object->property("loading").toBool(), true);
914 QCOMPARE(object->property("done").toBool(), true);
915 QCOMPARE(object->property("reset").toBool(), true);
920 void tst_qdeclarativexmlhttprequest::responseText_data()
922 QTest::addColumn<QUrl>("replyUrl");
923 QTest::addColumn<QUrl>("bodyUrl");
924 QTest::addColumn<QString>("responseText");
926 QTest::newRow("OK") << TEST_FILE("status.200.reply") << TEST_FILE("testdocument.html") << "QML Rocks!\n";
927 QTest::newRow("empty body") << TEST_FILE("status.200.reply") << QUrl() << "";
928 QTest::newRow("Not Found") << TEST_FILE("status.404.reply") << TEST_FILE("testdocument.html") << "";
931 void tst_qdeclarativexmlhttprequest::nonUtf8()
933 QFETCH(QString, fileName);
934 QFETCH(QString, responseText);
935 QFETCH(QString, xmlRootNodeValue);
937 QDeclarativeComponent component(&engine, TEST_FILE("utf16.qml"));
938 QObject *object = component.create();
939 QVERIFY(object != 0);
941 object->setProperty("fileName", fileName);
942 QMetaObject::invokeMethod(object, "startRequest");
944 QTRY_VERIFY(object->property("dataOK").toBool() == true);
946 QCOMPARE(object->property("responseText").toString(), responseText);
948 if (!xmlRootNodeValue.isEmpty()) {
949 QString rootNodeValue = object->property("responseXmlRootNodeValue").toString();
950 QCOMPARE(rootNodeValue, xmlRootNodeValue);
956 void tst_qdeclarativexmlhttprequest::nonUtf8_data()
958 QTest::addColumn<QString>("fileName");
959 QTest::addColumn<QString>("responseText");
960 QTest::addColumn<QString>("xmlRootNodeValue");
964 uc[0] = QChar(0x10e3);
966 uc[2] = QChar(0x03a3);
968 QTest::newRow("responseText") << "utf16.html" << uc + '\n' << "";
969 QTest::newRow("responseXML") << "utf16.xml" << "<?xml version=\"1.0\" encoding=\"UTF-16\" standalone='yes'?>\n<root>\n" + uc + "\n</root>\n" << QString('\n' + uc + '\n');
972 // Test that calling hte XMLHttpRequest methods on a non-XMLHttpRequest object
973 // throws an exception
974 void tst_qdeclarativexmlhttprequest::invalidMethodUsage()
976 QDeclarativeComponent component(&engine, TEST_FILE("invalidMethodUsage.qml"));
977 QObject *object = component.create();
978 QVERIFY(object != 0);
980 QCOMPARE(object->property("onreadystatechange").toBool(), true);
981 QCOMPARE(object->property("readyState").toBool(), true);
982 QCOMPARE(object->property("status").toBool(), true);
983 QCOMPARE(object->property("statusText").toBool(), true);
984 QCOMPARE(object->property("responseText").toBool(), true);
985 QCOMPARE(object->property("responseXML").toBool(), true);
987 QCOMPARE(object->property("open").toBool(), true);
988 QCOMPARE(object->property("setRequestHeader").toBool(), true);
989 QCOMPARE(object->property("send").toBool(), true);
990 QCOMPARE(object->property("abort").toBool(), true);
991 QCOMPARE(object->property("getResponseHeader").toBool(), true);
992 QCOMPARE(object->property("getAllResponseHeaders").toBool(), true);
997 // Test that XMLHttpRequest transparently redirects
998 void tst_qdeclarativexmlhttprequest::redirects()
1001 TestHTTPServer server(SERVER_PORT);
1002 QVERIFY(server.isValid());
1003 server.addRedirect("redirect.html", "http://127.0.0.1:14445/redirecttarget.html");
1004 server.serveDirectory(SRCDIR "/data");
1006 QDeclarativeComponent component(&engine, TEST_FILE("redirects.qml"));
1007 QObject *object = component.beginCreate(engine.rootContext());
1008 QVERIFY(object != 0);
1009 object->setProperty("url", "http://127.0.0.1:14445/redirect.html");
1010 object->setProperty("expectedText", "");
1011 component.completeCreate();
1013 QTRY_VERIFY(object->property("done").toBool() == true);
1014 QCOMPARE(object->property("dataOK").toBool(), true);
1020 TestHTTPServer server(SERVER_PORT);
1021 QVERIFY(server.isValid());
1022 server.addRedirect("redirect.html", "http://127.0.0.1:14445/redirectmissing.html");
1023 server.serveDirectory(SRCDIR "/data");
1025 QDeclarativeComponent component(&engine, TEST_FILE("redirectError.qml"));
1026 QObject *object = component.beginCreate(engine.rootContext());
1027 QVERIFY(object != 0);
1028 object->setProperty("url", "http://127.0.0.1:14445/redirect.html");
1029 object->setProperty("expectedText", "");
1030 component.completeCreate();
1032 QTRY_VERIFY(object->property("done").toBool() == true);
1033 QCOMPARE(object->property("dataOK").toBool(), true);
1039 TestHTTPServer server(SERVER_PORT);
1040 QVERIFY(server.isValid());
1041 server.addRedirect("redirect.html", "http://127.0.0.1:14445/redirect.html");
1042 server.serveDirectory(SRCDIR "/data");
1044 QDeclarativeComponent component(&engine, TEST_FILE("redirectRecur.qml"));
1045 QObject *object = component.beginCreate(engine.rootContext());
1046 QVERIFY(object != 0);
1047 object->setProperty("url", "http://127.0.0.1:14445/redirect.html");
1048 object->setProperty("expectedText", "");
1049 component.completeCreate();
1051 for (int ii = 0; ii < 60; ++ii) {
1052 if (object->property("done").toBool()) break;
1055 QVERIFY(object->property("done").toBool() == true);
1057 QCOMPARE(object->property("dataOK").toBool(), true);
1063 void tst_qdeclarativexmlhttprequest::responseXML_invalid()
1065 QDeclarativeComponent component(&engine, TEST_FILE("responseXML_invalid.qml"));
1066 QObject *object = component.create();
1067 QVERIFY(object != 0);
1069 QTRY_VERIFY(object->property("dataOK").toBool() == true);
1071 QCOMPARE(object->property("xmlNull").toBool(), true);
1076 // Test the Document DOM element
1077 void tst_qdeclarativexmlhttprequest::document()
1079 QDeclarativeComponent component(&engine, TEST_FILE("document.qml"));
1080 QObject *object = component.create();
1081 QVERIFY(object != 0);
1083 QTRY_VERIFY(object->property("dataOK").toBool() == true);
1085 QCOMPARE(object->property("xmlTest").toBool(), true);
1090 // Test the Element DOM element
1091 void tst_qdeclarativexmlhttprequest::element()
1093 QDeclarativeComponent component(&engine, TEST_FILE("element.qml"));
1094 QObject *object = component.create();
1095 QVERIFY(object != 0);
1097 QTRY_VERIFY(object->property("dataOK").toBool() == true);
1099 QCOMPARE(object->property("xmlTest").toBool(), true);
1104 // Test the Attr DOM element
1105 void tst_qdeclarativexmlhttprequest::attr()
1107 QDeclarativeComponent component(&engine, TEST_FILE("attr.qml"));
1108 QObject *object = component.create();
1109 QVERIFY(object != 0);
1111 QTRY_VERIFY(object->property("dataOK").toBool() == true);
1113 QCOMPARE(object->property("xmlTest").toBool(), true);
1118 // Test the Text DOM element
1119 void tst_qdeclarativexmlhttprequest::text()
1121 QDeclarativeComponent component(&engine, TEST_FILE("text.qml"));
1122 QObject *object = component.create();
1123 QVERIFY(object != 0);
1125 QTRY_VERIFY(object->property("dataOK").toBool() == true);
1127 QCOMPARE(object->property("xmlTest").toBool(), true);
1132 // Test the CDataSection DOM element
1133 void tst_qdeclarativexmlhttprequest::cdata()
1135 QDeclarativeComponent component(&engine, TEST_FILE("cdata.qml"));
1136 QObject *object = component.create();
1137 QVERIFY(object != 0);
1139 QTRY_VERIFY(object->property("dataOK").toBool() == true);
1141 QCOMPARE(object->property("xmlTest").toBool(), true);
1146 QTEST_MAIN(tst_qdeclarativexmlhttprequest)
1148 #include "tst_qdeclarativexmlhttprequest.moc"