1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
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 <QScopedPointer>
47 #include <QNetworkCookieJar>
48 #include "testhttpserver.h"
49 #include "../../shared/util.h"
51 #define SERVER_PORT 14445
53 class tst_qdeclarativexmlhttprequest : public QDeclarativeDataTest
57 tst_qdeclarativexmlhttprequest() {}
60 void domExceptionCodes();
61 void callbackException();
62 void callbackException_data();
63 void staticStateValues();
64 void instanceStateValues();
69 void open_invalid_method();
71 void open_arg_count();
72 void setRequestHeader();
73 void setRequestHeader_caseInsensitive();
74 void setRequestHeader_unsent();
75 void setRequestHeader_illegalName_data();
76 void setRequestHeader_illegalName();
77 void setRequestHeader_sent();
78 void setRequestHeader_args();
80 void send_alreadySent();
81 void send_ignoreData();
83 void send_withdata_data();
87 void getResponseHeader();
88 void getResponseHeader_unsent();
89 void getResponseHeader_sent();
90 void getResponseHeader_args();
91 void getAllResponseHeaders();
92 void getAllResponseHeaders_unsent();
93 void getAllResponseHeaders_sent();
94 void getAllResponseHeaders_args();
98 void statusText_data();
100 void responseText_data();
101 void responseXML_invalid();
102 void invalidMethodUsage();
115 // void outstanding_request_at_shutdown();
117 // void network_errors()
121 QDeclarativeEngine engine;
124 // Test that the dom exception codes are correct
125 void tst_qdeclarativexmlhttprequest::domExceptionCodes()
127 QDeclarativeComponent component(&engine, testFileUrl("domExceptionCodes.qml"));
128 QObject *object = component.create();
129 QVERIFY(object != 0);
131 QCOMPARE(object->property("index_size_err").toInt(), 1);
132 QCOMPARE(object->property("domstring_size_err").toInt(), 2);
133 QCOMPARE(object->property("hierarchy_request_err").toInt(), 3);
134 QCOMPARE(object->property("wrong_document_err").toInt(), 4);
135 QCOMPARE(object->property("invalid_character_err").toInt(), 5);
136 QCOMPARE(object->property("no_data_allowed_err").toInt(), 6);
137 QCOMPARE(object->property("no_modification_allowed_err").toInt(), 7);
138 QCOMPARE(object->property("not_found_err").toInt(), 8);
139 QCOMPARE(object->property("not_supported_err").toInt(), 9);
140 QCOMPARE(object->property("inuse_attribute_err").toInt(), 10);
141 QCOMPARE(object->property("invalid_state_err").toInt(), 11);
142 QCOMPARE(object->property("syntax_err").toInt(), 12);
143 QCOMPARE(object->property("invalid_modification_err").toInt(), 13);
144 QCOMPARE(object->property("namespace_err").toInt(), 14);
145 QCOMPARE(object->property("invalid_access_err").toInt(), 15);
146 QCOMPARE(object->property("validation_err").toInt(), 16);
147 QCOMPARE(object->property("type_mismatch_err").toInt(), 17);
152 void tst_qdeclarativexmlhttprequest::callbackException_data()
154 QTest::addColumn<QString>("which");
155 QTest::addColumn<int>("line");
157 QTest::newRow("on-opened") << "1" << 15;
158 QTest::newRow("on-loading") << "3" << 15;
159 QTest::newRow("on-done") << "4" << 15;
162 void tst_qdeclarativexmlhttprequest::callbackException()
164 // Test exception reporting for exceptions thrown at various points.
166 QFETCH(QString, which);
169 QString expect = testFileUrl("callbackException.qml").toString() + ":"+QString::number(line)+": Error: Exception from Callback";
170 QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
172 QDeclarativeComponent component(&engine, testFileUrl("callbackException.qml"));
173 QObject *object = component.beginCreate(engine.rootContext());
174 QVERIFY(object != 0);
175 object->setProperty("url", "testdocument.html");
176 object->setProperty("which", which);
177 component.completeCreate();
179 QTRY_VERIFY(object->property("threw").toBool() == true);
184 // Test that the state value properties on the XMLHttpRequest constructor have the correct values.
185 // ### WebKit does not do this, but it seems to fit the standard and QML better
186 void tst_qdeclarativexmlhttprequest::staticStateValues()
188 QDeclarativeComponent component(&engine, testFileUrl("staticStateValues.qml"));
189 QObject *object = component.create();
190 QVERIFY(object != 0);
192 QCOMPARE(object->property("unsent").toInt(), 0);
193 QCOMPARE(object->property("opened").toInt(), 1);
194 QCOMPARE(object->property("headers_received").toInt(), 2);
195 QCOMPARE(object->property("loading").toInt(), 3);
196 QCOMPARE(object->property("done").toInt(), 4);
201 // Test that the state value properties on instances have the correct values.
202 void tst_qdeclarativexmlhttprequest::instanceStateValues()
204 QDeclarativeComponent component(&engine, testFileUrl("instanceStateValues.qml"));
205 QObject *object = component.create();
206 QVERIFY(object != 0);
208 QCOMPARE(object->property("unsent").toInt(), 0);
209 QCOMPARE(object->property("opened").toInt(), 1);
210 QCOMPARE(object->property("headers_received").toInt(), 2);
211 QCOMPARE(object->property("loading").toInt(), 3);
212 QCOMPARE(object->property("done").toInt(), 4);
217 // Test calling constructor
218 void tst_qdeclarativexmlhttprequest::constructor()
220 QDeclarativeComponent component(&engine, testFileUrl("constructor.qml"));
221 QObject *object = component.create();
222 QVERIFY(object != 0);
224 QCOMPARE(object->property("calledAsConstructor").toBool(), true);
225 QCOMPARE(object->property("calledAsFunction").toBool(), true);
230 // Test that all the properties are set correctly before any request is sent
231 void tst_qdeclarativexmlhttprequest::defaultState()
233 QDeclarativeComponent component(&engine, testFileUrl("defaultState.qml"));
234 QObject *object = component.create();
235 QVERIFY(object != 0);
237 QCOMPARE(object->property("readState").toInt(), 0);
238 QCOMPARE(object->property("statusIsException").toBool(), true);
239 QCOMPARE(object->property("statusTextIsException").toBool(), true);
240 QCOMPARE(object->property("responseText").toString(), QString());
241 QCOMPARE(object->property("responseXMLIsNull").toBool(), true);
246 // Test valid XMLHttpRequest.open() calls
247 void tst_qdeclarativexmlhttprequest::open()
249 QFETCH(QUrl, qmlFile);
250 QFETCH(QString, url);
251 QFETCH(bool, remote);
253 QScopedPointer<TestHTTPServer> server; // ensure deletion in case test fails
255 server.reset(new TestHTTPServer(SERVER_PORT));
256 QVERIFY(server->isValid());
257 QVERIFY(server->wait(testFileUrl("open_network.expect"),
258 testFileUrl("open_network.reply"),
259 testFileUrl("testdocument.html")));
262 QDeclarativeComponent component(&engine, qmlFile);
263 QObject *object = component.beginCreate(engine.rootContext());
264 QVERIFY(object != 0);
265 object->setProperty("url", url);
266 component.completeCreate();
268 QCOMPARE(object->property("readyState").toBool(), true);
269 QCOMPARE(object->property("openedState").toBool(), true);
270 QCOMPARE(object->property("status").toBool(), true);
271 QCOMPARE(object->property("statusText").toBool(), true);
272 QCOMPARE(object->property("responseText").toBool(), true);
273 QCOMPARE(object->property("responseXML").toBool(), true);
275 QTRY_VERIFY(object->property("dataOK").toBool() == true);
280 void tst_qdeclarativexmlhttprequest::open_data()
282 QTest::addColumn<QUrl>("qmlFile");
283 QTest::addColumn<QString>("url");
284 QTest::addColumn<bool>("remote");
286 QTest::newRow("Relative url)") << testFileUrl("open.qml") << "testdocument.html" << false;
287 QTest::newRow("Absolute url)") << testFileUrl("open.qml") << testFileUrl("testdocument.html").toString() << false;
288 QTest::newRow("Absolute network url)") << testFileUrl("open.qml") << "http://127.0.0.1:14445/testdocument.html" << true;
290 // ### Check that the username/password were sent to the server
291 QTest::newRow("User/pass") << testFileUrl("open_user.qml") << "http://127.0.0.1:14445/testdocument.html" << true;
294 // Test that calling XMLHttpRequest.open() with an invalid method raises an exception
295 void tst_qdeclarativexmlhttprequest::open_invalid_method()
297 QDeclarativeComponent component(&engine, testFileUrl("open_invalid_method.qml"));
298 QObject *object = component.create();
299 QVERIFY(object != 0);
301 QCOMPARE(object->property("exceptionThrown").toBool(), true);
306 // Test that calling XMLHttpRequest.open() with sync raises an exception
307 void tst_qdeclarativexmlhttprequest::open_sync()
309 QDeclarativeComponent component(&engine, testFileUrl("open_sync.qml"));
310 QObject *object = component.create();
311 QVERIFY(object != 0);
313 QCOMPARE(object->property("exceptionThrown").toBool(), true);
318 // Calling with incorrect arg count raises an exception
319 void tst_qdeclarativexmlhttprequest::open_arg_count()
322 QDeclarativeComponent component(&engine, testFileUrl("open_arg_count.1.qml"));
323 QObject *object = component.create();
324 QVERIFY(object != 0);
326 QCOMPARE(object->property("exceptionThrown").toBool(), true);
332 QDeclarativeComponent component(&engine, testFileUrl("open_arg_count.2.qml"));
333 QObject *object = component.create();
334 QVERIFY(object != 0);
336 QCOMPARE(object->property("exceptionThrown").toBool(), true);
342 // Test valid setRequestHeader() calls
343 void tst_qdeclarativexmlhttprequest::setRequestHeader()
345 TestHTTPServer server(SERVER_PORT);
346 QVERIFY(server.isValid());
347 QVERIFY(server.wait(testFileUrl("setRequestHeader.expect"),
348 testFileUrl("setRequestHeader.reply"),
349 testFileUrl("testdocument.html")));
351 QDeclarativeComponent component(&engine, testFileUrl("setRequestHeader.qml"));
352 QObject *object = component.beginCreate(engine.rootContext());
353 QVERIFY(object != 0);
354 object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
355 component.completeCreate();
357 QTRY_VERIFY(object->property("dataOK").toBool() == true);
362 // Test valid setRequestHeader() calls with different header cases
363 void tst_qdeclarativexmlhttprequest::setRequestHeader_caseInsensitive()
365 TestHTTPServer server(SERVER_PORT);
366 QVERIFY(server.isValid());
367 QVERIFY(server.wait(testFileUrl("setRequestHeader.expect"),
368 testFileUrl("setRequestHeader.reply"),
369 testFileUrl("testdocument.html")));
371 QDeclarativeComponent component(&engine, testFileUrl("setRequestHeader_caseInsensitive.qml"));
372 QObject *object = component.beginCreate(engine.rootContext());
373 QVERIFY(object != 0);
374 object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
375 component.completeCreate();
377 QTRY_VERIFY(object->property("dataOK").toBool() == true);
381 // Test setting headers before open() throws exception
382 void tst_qdeclarativexmlhttprequest::setRequestHeader_unsent()
384 QDeclarativeComponent component(&engine, testFileUrl("setRequestHeader_unsent.qml"));
385 QObject *object = component.create();
386 QVERIFY(object != 0);
388 QCOMPARE(object->property("test").toBool(), true);
393 void tst_qdeclarativexmlhttprequest::setRequestHeader_illegalName_data()
395 QTest::addColumn<QString>("name");
397 QTest::newRow("Accept-Charset") << "AccePT-CHArset";
398 QTest::newRow("Accept-Encoding") << "AccEpt-EnCOding";
399 QTest::newRow("Connection") << "ConnECtion";
400 QTest::newRow("Content-Length") << "ContEnt-LenGth";
401 QTest::newRow("Cookie") << "CookIe";
402 QTest::newRow("Cookie2") << "CoOkie2";
403 QTest::newRow("Content-Transfer-Encoding") << "ConteNT-tRANSFER-eNCOding";
404 QTest::newRow("Date") << "DaTE";
405 QTest::newRow("Expect") << "ExPect";
406 QTest::newRow("Host") << "HoST";
407 QTest::newRow("Keep-Alive") << "KEEP-aLive";
408 QTest::newRow("Referer") << "ReferEr";
409 QTest::newRow("TE") << "Te";
410 QTest::newRow("Trailer") << "TraILEr";
411 QTest::newRow("Transfer-Encoding") << "tRANsfer-Encoding";
412 QTest::newRow("Upgrade") << "UpgrADe";
413 QTest::newRow("User-Agent") << "uSEr-Agent";
414 QTest::newRow("Via") << "vIa";
415 QTest::newRow("Proxy-") << "ProXy-";
416 QTest::newRow("Sec-") << "SeC-";
417 QTest::newRow("Proxy-*") << "Proxy-BLAH";
418 QTest::newRow("Sec-*") << "Sec-F";
421 // Tests that using illegal header names has no effect
422 void tst_qdeclarativexmlhttprequest::setRequestHeader_illegalName()
424 QFETCH(QString, name);
426 TestHTTPServer server(SERVER_PORT);
427 QVERIFY(server.isValid());
428 QVERIFY(server.wait(testFileUrl("open_network.expect"),
429 testFileUrl("open_network.reply"),
430 testFileUrl("testdocument.html")));
432 QDeclarativeComponent component(&engine, testFileUrl("setRequestHeader_illegalName.qml"));
433 QObject *object = component.beginCreate(engine.rootContext());
434 QVERIFY(object != 0);
435 object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
436 object->setProperty("header", name);
437 component.completeCreate();
439 QCOMPARE(object->property("readyState").toBool(), true);
440 QCOMPARE(object->property("openedState").toBool(), true);
441 QCOMPARE(object->property("status").toBool(), true);
442 QCOMPARE(object->property("statusText").toBool(), true);
443 QCOMPARE(object->property("responseText").toBool(), true);
444 QCOMPARE(object->property("responseXML").toBool(), true);
446 QTRY_VERIFY(object->property("dataOK").toBool() == true);
451 // Test that attempting to set a header after a request is sent throws an exception
452 void tst_qdeclarativexmlhttprequest::setRequestHeader_sent()
454 TestHTTPServer server(SERVER_PORT);
455 QVERIFY(server.isValid());
456 QVERIFY(server.wait(testFileUrl("open_network.expect"),
457 testFileUrl("open_network.reply"),
458 testFileUrl("testdocument.html")));
460 QDeclarativeComponent component(&engine, testFileUrl("setRequestHeader_sent.qml"));
461 QObject *object = component.beginCreate(engine.rootContext());
462 QVERIFY(object != 0);
463 object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
464 component.completeCreate();
466 QCOMPARE(object->property("test").toBool(), true);
468 QTRY_VERIFY(object->property("dataOK").toBool() == true);
473 // Invalid arg count throws exception
474 void tst_qdeclarativexmlhttprequest::setRequestHeader_args()
476 QDeclarativeComponent component(&engine, testFileUrl("setRequestHeader_args.qml"));
477 QObject *object = component.create();
478 QVERIFY(object != 0);
480 QCOMPARE(object->property("exceptionThrown").toBool(), true);
485 // Test that calling send() in UNSENT state throws an exception
486 void tst_qdeclarativexmlhttprequest::send_unsent()
488 QDeclarativeComponent component(&engine, testFileUrl("send_unsent.qml"));
489 QObject *object = component.create();
490 QVERIFY(object != 0);
492 QCOMPARE(object->property("test").toBool(), true);
497 // Test attempting to resend a sent request throws an exception
498 void tst_qdeclarativexmlhttprequest::send_alreadySent()
500 QDeclarativeComponent component(&engine, testFileUrl("send_alreadySent.qml"));
501 QObject *object = component.create();
502 QVERIFY(object != 0);
504 QCOMPARE(object->property("test").toBool(), true);
505 QTRY_VERIFY(object->property("dataOK").toBool() == true);
510 // Test that sends for GET, HEAD and DELETE ignore data
511 void tst_qdeclarativexmlhttprequest::send_ignoreData()
514 TestHTTPServer server(SERVER_PORT);
515 QVERIFY(server.isValid());
516 QVERIFY(server.wait(testFileUrl("send_ignoreData_GET.expect"),
517 testFileUrl("send_ignoreData.reply"),
518 testFileUrl("testdocument.html")));
520 QDeclarativeComponent component(&engine, testFileUrl("send_ignoreData.qml"));
521 QObject *object = component.beginCreate(engine.rootContext());
522 QVERIFY(object != 0);
523 object->setProperty("reqType", "GET");
524 object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
525 component.completeCreate();
527 QTRY_VERIFY(object->property("dataOK").toBool() == true);
533 TestHTTPServer server(SERVER_PORT);
534 QVERIFY(server.isValid());
535 QVERIFY(server.wait(testFileUrl("send_ignoreData_HEAD.expect"),
536 testFileUrl("send_ignoreData.reply"),
539 QDeclarativeComponent component(&engine, testFileUrl("send_ignoreData.qml"));
540 QObject *object = component.beginCreate(engine.rootContext());
541 QVERIFY(object != 0);
542 object->setProperty("reqType", "HEAD");
543 object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
544 component.completeCreate();
546 QTRY_VERIFY(object->property("dataOK").toBool() == true);
552 TestHTTPServer server(SERVER_PORT);
553 QVERIFY(server.isValid());
554 QVERIFY(server.wait(testFileUrl("send_ignoreData_DELETE.expect"),
555 testFileUrl("send_ignoreData.reply"),
558 QDeclarativeComponent component(&engine, testFileUrl("send_ignoreData.qml"));
559 QObject *object = component.beginCreate(engine.rootContext());
560 QVERIFY(object != 0);
561 object->setProperty("reqType", "DELETE");
562 object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
563 component.completeCreate();
565 QTRY_VERIFY(object->property("dataOK").toBool() == true);
571 // Test that send()'ing data works
572 void tst_qdeclarativexmlhttprequest::send_withdata()
574 QFETCH(QString, file_expected);
575 QFETCH(QString, file_qml);
577 TestHTTPServer server(SERVER_PORT);
578 QVERIFY(server.isValid());
579 QVERIFY(server.wait(testFileUrl(file_expected),
580 testFileUrl("send_data.reply"),
581 testFileUrl("testdocument.html")));
583 QDeclarativeComponent component(&engine, testFileUrl(file_qml));
584 QObject *object = component.beginCreate(engine.rootContext());
585 QVERIFY(object != 0);
586 object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
587 component.completeCreate();
589 QTRY_VERIFY(object->property("dataOK").toBool() == true);
594 void tst_qdeclarativexmlhttprequest::send_withdata_data()
596 QTest::addColumn<QString>("file_expected");
597 QTest::addColumn<QString>("file_qml");
599 QTest::newRow("No content-type") << "send_data.1.expect" << "send_data.1.qml";
600 QTest::newRow("Correct content-type") << "send_data.1.expect" << "send_data.2.qml";
601 QTest::newRow("Incorrect content-type") << "send_data.1.expect" << "send_data.3.qml";
602 QTest::newRow("Correct content-type - out of order") << "send_data.4.expect" << "send_data.4.qml";
603 QTest::newRow("Incorrect content-type - out of order") << "send_data.4.expect" << "send_data.5.qml";
604 QTest::newRow("PUT") << "send_data.6.expect" << "send_data.6.qml";
605 QTest::newRow("Correct content-type - no charset") << "send_data.1.expect" << "send_data.7.qml";
608 // Test abort() has no effect in unsent state
609 void tst_qdeclarativexmlhttprequest::abort_unsent()
611 QDeclarativeComponent component(&engine, testFileUrl("abort_unsent.qml"));
612 QObject *object = component.beginCreate(engine.rootContext());
613 QVERIFY(object != 0);
614 object->setProperty("url", "testdocument.html");
615 component.completeCreate();
617 QCOMPARE(object->property("readyState").toBool(), true);
618 QCOMPARE(object->property("openedState").toBool(), true);
619 QCOMPARE(object->property("status").toBool(), true);
620 QCOMPARE(object->property("statusText").toBool(), true);
621 QCOMPARE(object->property("responseText").toBool(), true);
622 QCOMPARE(object->property("responseXML").toBool(), true);
624 QTRY_VERIFY(object->property("dataOK").toBool() == true);
629 // Test abort() cancels an open (but unsent) request
630 void tst_qdeclarativexmlhttprequest::abort_opened()
632 QDeclarativeComponent component(&engine, testFileUrl("abort_opened.qml"));
633 QObject *object = component.beginCreate(engine.rootContext());
634 QVERIFY(object != 0);
635 object->setProperty("url", "testdocument.html");
636 component.completeCreate();
638 QCOMPARE(object->property("readyState").toBool(), true);
639 QCOMPARE(object->property("openedState").toBool(), true);
640 QCOMPARE(object->property("status").toBool(), true);
641 QCOMPARE(object->property("statusText").toBool(), true);
642 QCOMPARE(object->property("responseText").toBool(), true);
643 QCOMPARE(object->property("responseXML").toBool(), true);
645 QTRY_VERIFY(object->property("dataOK").toBool() == true);
650 // Test abort() aborts in progress send
651 void tst_qdeclarativexmlhttprequest::abort()
653 TestHTTPServer server(SERVER_PORT);
654 QVERIFY(server.isValid());
655 QVERIFY(server.wait(testFileUrl("abort.expect"),
656 testFileUrl("abort.reply"),
657 testFileUrl("testdocument.html")));
659 QDeclarativeComponent component(&engine, testFileUrl("abort.qml"));
660 QObject *object = component.beginCreate(engine.rootContext());
661 QVERIFY(object != 0);
662 object->setProperty("urlDummy", "http://127.0.0.1:14449/testdocument.html");
663 object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
664 component.completeCreate();
666 QCOMPARE(object->property("seenDone").toBool(), true);
667 QCOMPARE(object->property("didNotSeeUnsent").toBool(), true);
668 QCOMPARE(object->property("endStateUnsent").toBool(), true);
670 QTRY_VERIFY(object->property("dataOK").toBool() == true);
675 void tst_qdeclarativexmlhttprequest::getResponseHeader()
677 QDeclarativeEngine engine; // Avoid cookie contamination
679 TestHTTPServer server(SERVER_PORT);
680 QVERIFY(server.isValid());
681 QVERIFY(server.wait(testFileUrl("getResponseHeader.expect"),
682 testFileUrl("getResponseHeader.reply"),
683 testFileUrl("testdocument.html")));
686 QDeclarativeComponent component(&engine, testFileUrl("getResponseHeader.qml"));
687 QObject *object = component.beginCreate(engine.rootContext());
688 QVERIFY(object != 0);
689 object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
690 component.completeCreate();
692 QCOMPARE(object->property("unsentException").toBool(), true);
693 QCOMPARE(object->property("openedException").toBool(), true);
694 QCOMPARE(object->property("readyState").toBool(), true);
695 QCOMPARE(object->property("openedState").toBool(), true);
697 QTRY_VERIFY(object->property("dataOK").toBool() == true);
699 QCOMPARE(object->property("headersReceivedState").toBool(), true);
700 QCOMPARE(object->property("headersReceivedNullHeader").toBool(), true);
701 QCOMPARE(object->property("headersReceivedValidHeader").toBool(), true);
702 QCOMPARE(object->property("headersReceivedMultiValidHeader").toBool(), true);
703 QCOMPARE(object->property("headersReceivedCookieHeader").toBool(), true);
705 QCOMPARE(object->property("doneState").toBool(), true);
706 QCOMPARE(object->property("doneNullHeader").toBool(), true);
707 QCOMPARE(object->property("doneValidHeader").toBool(), true);
708 QCOMPARE(object->property("doneMultiValidHeader").toBool(), true);
709 QCOMPARE(object->property("doneCookieHeader").toBool(), true);
714 // Test getResponseHeader throws an exception in an invalid state
715 void tst_qdeclarativexmlhttprequest::getResponseHeader_unsent()
717 QDeclarativeComponent component(&engine, testFileUrl("getResponseHeader_unsent.qml"));
718 QObject *object = component.create();
719 QVERIFY(object != 0);
721 QCOMPARE(object->property("test").toBool(), true);
726 // Test getResponseHeader throws an exception in an invalid state
727 void tst_qdeclarativexmlhttprequest::getResponseHeader_sent()
729 QDeclarativeComponent component(&engine, testFileUrl("getResponseHeader_sent.qml"));
730 QObject *object = component.create();
731 QVERIFY(object != 0);
733 QCOMPARE(object->property("test").toBool(), true);
738 // Invalid arg count throws exception
739 void tst_qdeclarativexmlhttprequest::getResponseHeader_args()
741 QDeclarativeComponent component(&engine, testFileUrl("getResponseHeader_args.qml"));
742 QObject *object = component.create();
743 QVERIFY(object != 0);
745 QTRY_VERIFY(object->property("exceptionThrown").toBool() == true);
750 void tst_qdeclarativexmlhttprequest::getAllResponseHeaders()
752 QDeclarativeEngine engine; // Avoid cookie contamination
754 TestHTTPServer server(SERVER_PORT);
755 QVERIFY(server.isValid());
756 QVERIFY(server.wait(testFileUrl("getResponseHeader.expect"),
757 testFileUrl("getResponseHeader.reply"),
758 testFileUrl("testdocument.html")));
760 QDeclarativeComponent component(&engine, testFileUrl("getAllResponseHeaders.qml"));
761 QObject *object = component.beginCreate(engine.rootContext());
762 QVERIFY(object != 0);
763 object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
764 component.completeCreate();
766 QCOMPARE(object->property("unsentException").toBool(), true);
767 QCOMPARE(object->property("openedException").toBool(), true);
768 QCOMPARE(object->property("readyState").toBool(), true);
769 QCOMPARE(object->property("openedState").toBool(), true);
771 QTRY_VERIFY(object->property("dataOK").toBool() == true);
773 QCOMPARE(object->property("headersReceivedState").toBool(), true);
774 QCOMPARE(object->property("headersReceivedHeader").toBool(), true);
776 QCOMPARE(object->property("doneState").toBool(), true);
777 QCOMPARE(object->property("doneHeader").toBool(), true);
782 // Test getAllResponseHeaders throws an exception in an invalid state
783 void tst_qdeclarativexmlhttprequest::getAllResponseHeaders_unsent()
785 QDeclarativeComponent component(&engine, testFileUrl("getAllResponseHeaders_unsent.qml"));
786 QObject *object = component.create();
787 QVERIFY(object != 0);
789 QCOMPARE(object->property("test").toBool(), true);
794 // Test getAllResponseHeaders throws an exception in an invalid state
795 void tst_qdeclarativexmlhttprequest::getAllResponseHeaders_sent()
797 QDeclarativeComponent component(&engine, testFileUrl("getAllResponseHeaders_sent.qml"));
798 QObject *object = component.create();
799 QVERIFY(object != 0);
801 QCOMPARE(object->property("test").toBool(), true);
806 // Invalid arg count throws exception
807 void tst_qdeclarativexmlhttprequest::getAllResponseHeaders_args()
809 QDeclarativeComponent component(&engine, testFileUrl("getAllResponseHeaders_args.qml"));
810 QObject *object = component.create();
811 QVERIFY(object != 0);
813 QTRY_VERIFY(object->property("exceptionThrown").toBool() == true);
818 void tst_qdeclarativexmlhttprequest::status()
820 QFETCH(QUrl, replyUrl);
823 TestHTTPServer server(SERVER_PORT);
824 QVERIFY(server.isValid());
825 QVERIFY(server.wait(testFileUrl("status.expect"),
827 testFileUrl("testdocument.html")));
829 QDeclarativeComponent component(&engine, testFileUrl("status.qml"));
830 QObject *object = component.beginCreate(engine.rootContext());
831 QVERIFY(object != 0);
832 object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
833 object->setProperty("expectedStatus", status);
834 component.completeCreate();
836 QTRY_VERIFY(object->property("dataOK").toBool() == true);
838 QCOMPARE(object->property("unsentException").toBool(), true);
839 QCOMPARE(object->property("openedException").toBool(), true);
840 QCOMPARE(object->property("sentException").toBool(), true);
841 QCOMPARE(object->property("headersReceived").toBool(), true);
842 QCOMPARE(object->property("loading").toBool(), true);
843 QCOMPARE(object->property("done").toBool(), true);
844 QCOMPARE(object->property("resetException").toBool(), true);
849 void tst_qdeclarativexmlhttprequest::status_data()
851 QTest::addColumn<QUrl>("replyUrl");
852 QTest::addColumn<int>("status");
854 QTest::newRow("OK") << testFileUrl("status.200.reply") << 200;
855 QTest::newRow("Not Found") << testFileUrl("status.404.reply") << 404;
856 QTest::newRow("Bad Request") << testFileUrl("status.400.reply") << 400;
859 void tst_qdeclarativexmlhttprequest::statusText()
861 QFETCH(QUrl, replyUrl);
862 QFETCH(QString, statusText);
864 TestHTTPServer server(SERVER_PORT);
865 QVERIFY(server.isValid());
866 QVERIFY(server.wait(testFileUrl("status.expect"),
868 testFileUrl("testdocument.html")));
870 QDeclarativeComponent component(&engine, testFileUrl("statusText.qml"));
871 QObject *object = component.beginCreate(engine.rootContext());
872 QVERIFY(object != 0);
873 object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
874 object->setProperty("expectedStatus", statusText);
875 component.completeCreate();
877 QTRY_VERIFY(object->property("dataOK").toBool() == true);
879 QCOMPARE(object->property("unsentException").toBool(), true);
880 QCOMPARE(object->property("openedException").toBool(), true);
881 QCOMPARE(object->property("sentException").toBool(), true);
882 QCOMPARE(object->property("headersReceived").toBool(), true);
883 QCOMPARE(object->property("loading").toBool(), true);
884 QCOMPARE(object->property("done").toBool(), true);
885 QCOMPARE(object->property("resetException").toBool(), true);
890 void tst_qdeclarativexmlhttprequest::statusText_data()
892 QTest::addColumn<QUrl>("replyUrl");
893 QTest::addColumn<QString>("statusText");
895 QTest::newRow("OK") << testFileUrl("status.200.reply") << "OK";
896 QTest::newRow("Not Found") << testFileUrl("status.404.reply") << "Document not found";
897 QTest::newRow("Bad Request") << testFileUrl("status.400.reply") << "Bad request";
900 void tst_qdeclarativexmlhttprequest::responseText()
902 QFETCH(QUrl, replyUrl);
903 QFETCH(QUrl, bodyUrl);
904 QFETCH(QString, responseText);
906 TestHTTPServer server(SERVER_PORT);
907 QVERIFY(server.isValid());
908 QVERIFY(server.wait(testFileUrl("status.expect"),
912 QDeclarativeComponent component(&engine, testFileUrl("responseText.qml"));
913 QObject *object = component.beginCreate(engine.rootContext());
914 QVERIFY(object != 0);
915 object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
916 object->setProperty("expectedText", responseText);
917 component.completeCreate();
919 QTRY_VERIFY(object->property("dataOK").toBool() == true);
921 QCOMPARE(object->property("unsent").toBool(), true);
922 QCOMPARE(object->property("opened").toBool(), true);
923 QCOMPARE(object->property("sent").toBool(), true);
924 QCOMPARE(object->property("headersReceived").toBool(), true);
925 QCOMPARE(object->property("loading").toBool(), true);
926 QCOMPARE(object->property("done").toBool(), true);
927 QCOMPARE(object->property("reset").toBool(), true);
932 void tst_qdeclarativexmlhttprequest::responseText_data()
934 QTest::addColumn<QUrl>("replyUrl");
935 QTest::addColumn<QUrl>("bodyUrl");
936 QTest::addColumn<QString>("responseText");
938 QTest::newRow("OK") << testFileUrl("status.200.reply") << testFileUrl("testdocument.html") << "QML Rocks!\n";
939 QTest::newRow("empty body") << testFileUrl("status.200.reply") << QUrl() << "";
940 QTest::newRow("Not Found") << testFileUrl("status.404.reply") << testFileUrl("testdocument.html") << "";
941 QTest::newRow("Bad Request") << testFileUrl("status.404.reply") << testFileUrl("testdocument.html") << "";
944 void tst_qdeclarativexmlhttprequest::nonUtf8()
946 QFETCH(QString, fileName);
947 QFETCH(QString, responseText);
948 QFETCH(QString, xmlRootNodeValue);
950 QDeclarativeComponent component(&engine, testFileUrl("utf16.qml"));
951 QObject *object = component.create();
952 QVERIFY(object != 0);
954 object->setProperty("fileName", fileName);
955 QMetaObject::invokeMethod(object, "startRequest");
957 QTRY_VERIFY(object->property("dataOK").toBool() == true);
959 QCOMPARE(object->property("responseText").toString(), responseText);
961 if (!xmlRootNodeValue.isEmpty()) {
962 QString rootNodeValue = object->property("responseXmlRootNodeValue").toString();
963 QCOMPARE(rootNodeValue, xmlRootNodeValue);
969 void tst_qdeclarativexmlhttprequest::nonUtf8_data()
971 QTest::addColumn<QString>("fileName");
972 QTest::addColumn<QString>("responseText");
973 QTest::addColumn<QString>("xmlRootNodeValue");
977 uc[0] = QChar(0x10e3);
979 uc[2] = QChar(0x03a3);
981 QTest::newRow("responseText") << "utf16.html" << uc + '\n' << "";
982 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');
985 // Test that calling hte XMLHttpRequest methods on a non-XMLHttpRequest object
986 // throws an exception
987 void tst_qdeclarativexmlhttprequest::invalidMethodUsage()
989 QDeclarativeComponent component(&engine, testFileUrl("invalidMethodUsage.qml"));
990 QObject *object = component.create();
991 QVERIFY(object != 0);
993 QCOMPARE(object->property("readyState").toBool(), true);
994 QCOMPARE(object->property("status").toBool(), true);
995 QCOMPARE(object->property("statusText").toBool(), true);
996 QCOMPARE(object->property("responseText").toBool(), true);
997 QCOMPARE(object->property("responseXML").toBool(), true);
999 QCOMPARE(object->property("open").toBool(), true);
1000 QCOMPARE(object->property("setRequestHeader").toBool(), true);
1001 QCOMPARE(object->property("send").toBool(), true);
1002 QCOMPARE(object->property("abort").toBool(), true);
1003 QCOMPARE(object->property("getResponseHeader").toBool(), true);
1004 QCOMPARE(object->property("getAllResponseHeaders").toBool(), true);
1009 // Test that XMLHttpRequest transparently redirects
1010 void tst_qdeclarativexmlhttprequest::redirects()
1013 TestHTTPServer server(SERVER_PORT);
1014 QVERIFY(server.isValid());
1015 server.addRedirect("redirect.html", "http://127.0.0.1:14445/redirecttarget.html");
1016 server.serveDirectory(dataDirectory());
1018 QDeclarativeComponent component(&engine, testFileUrl("redirects.qml"));
1019 QObject *object = component.beginCreate(engine.rootContext());
1020 QVERIFY(object != 0);
1021 object->setProperty("url", "http://127.0.0.1:14445/redirect.html");
1022 object->setProperty("expectedText", "");
1023 component.completeCreate();
1025 QTRY_VERIFY(object->property("done").toBool() == true);
1026 QCOMPARE(object->property("dataOK").toBool(), true);
1032 TestHTTPServer server(SERVER_PORT);
1033 QVERIFY(server.isValid());
1034 server.addRedirect("redirect.html", "http://127.0.0.1:14445/redirectmissing.html");
1035 server.serveDirectory(dataDirectory());
1037 QDeclarativeComponent component(&engine, testFileUrl("redirectError.qml"));
1038 QObject *object = component.beginCreate(engine.rootContext());
1039 QVERIFY(object != 0);
1040 object->setProperty("url", "http://127.0.0.1:14445/redirect.html");
1041 object->setProperty("expectedText", "");
1042 component.completeCreate();
1044 QTRY_VERIFY(object->property("done").toBool() == true);
1045 QCOMPARE(object->property("dataOK").toBool(), true);
1051 TestHTTPServer server(SERVER_PORT);
1052 QVERIFY(server.isValid());
1053 server.addRedirect("redirect.html", "http://127.0.0.1:14445/redirect.html");
1054 server.serveDirectory(dataDirectory());
1056 QDeclarativeComponent component(&engine, testFileUrl("redirectRecur.qml"));
1057 QObject *object = component.beginCreate(engine.rootContext());
1058 QVERIFY(object != 0);
1059 object->setProperty("url", "http://127.0.0.1:14445/redirect.html");
1060 object->setProperty("expectedText", "");
1061 component.completeCreate();
1063 for (int ii = 0; ii < 60; ++ii) {
1064 if (object->property("done").toBool()) break;
1067 QVERIFY(object->property("done").toBool() == true);
1069 QCOMPARE(object->property("dataOK").toBool(), true);
1075 void tst_qdeclarativexmlhttprequest::responseXML_invalid()
1077 QDeclarativeComponent component(&engine, testFileUrl("responseXML_invalid.qml"));
1078 QObject *object = component.create();
1079 QVERIFY(object != 0);
1081 QTRY_VERIFY(object->property("dataOK").toBool() == true);
1083 QCOMPARE(object->property("xmlNull").toBool(), true);
1088 // Test the Document DOM element
1089 void tst_qdeclarativexmlhttprequest::document()
1091 QDeclarativeComponent component(&engine, testFileUrl("document.qml"));
1092 QObject *object = component.create();
1093 QVERIFY(object != 0);
1095 QTRY_VERIFY(object->property("dataOK").toBool() == true);
1097 QCOMPARE(object->property("xmlTest").toBool(), true);
1102 // Test the Element DOM element
1103 void tst_qdeclarativexmlhttprequest::element()
1105 QDeclarativeComponent component(&engine, testFileUrl("element.qml"));
1106 QObject *object = component.create();
1107 QVERIFY(object != 0);
1109 QTRY_VERIFY(object->property("dataOK").toBool() == true);
1111 QCOMPARE(object->property("xmlTest").toBool(), true);
1116 // Test the Attr DOM element
1117 void tst_qdeclarativexmlhttprequest::attr()
1119 QDeclarativeComponent component(&engine, testFileUrl("attr.qml"));
1120 QObject *object = component.create();
1121 QVERIFY(object != 0);
1123 QTRY_VERIFY(object->property("dataOK").toBool() == true);
1125 QCOMPARE(object->property("xmlTest").toBool(), true);
1130 // Test the Text DOM element
1131 void tst_qdeclarativexmlhttprequest::text()
1133 QDeclarativeComponent component(&engine, testFileUrl("text.qml"));
1134 QObject *object = component.create();
1135 QVERIFY(object != 0);
1137 QTRY_VERIFY(object->property("dataOK").toBool() == true);
1139 QCOMPARE(object->property("xmlTest").toBool(), true);
1144 // Test the CDataSection DOM element
1145 void tst_qdeclarativexmlhttprequest::cdata()
1147 QDeclarativeComponent component(&engine, testFileUrl("cdata.qml"));
1148 QObject *object = component.create();
1149 QVERIFY(object != 0);
1151 QTRY_VERIFY(object->property("dataOK").toBool() == true);
1153 QCOMPARE(object->property("xmlTest").toBool(), true);
1158 QTEST_MAIN(tst_qdeclarativexmlhttprequest)
1160 #include "tst_qdeclarativexmlhttprequest.moc"