diff options
author | Aaron Kennedy <aaron.kennedy@nokia.com> | 2009-11-10 04:53:36 (GMT) |
---|---|---|
committer | Aaron Kennedy <aaron.kennedy@nokia.com> | 2009-11-10 06:52:02 (GMT) |
commit | bdb9c0ffa84bfab386de5550bd8f9b013288daca (patch) | |
tree | 54e0d7d8fa31271476caa053abcab37f1436d36d | |
parent | 4983b04da9f3258519e4b15f8e593bf2a11f3556 (diff) | |
download | Qt-bdb9c0ffa84bfab386de5550bd8f9b013288daca.zip Qt-bdb9c0ffa84bfab386de5550bd8f9b013288daca.tar.gz Qt-bdb9c0ffa84bfab386de5550bd8f9b013288daca.tar.bz2 |
XMLHttpRequest tests
25 files changed, 1304 insertions, 15 deletions
diff --git a/src/declarative/qml/qmlxmlhttprequest.cpp b/src/declarative/qml/qmlxmlhttprequest.cpp index 6946e7a..a6cdfb1 100644 --- a/src/declarative/qml/qmlxmlhttprequest.cpp +++ b/src/declarative/qml/qmlxmlhttprequest.cpp @@ -134,7 +134,7 @@ public: class DocumentImpl : public QmlRefCount { public: - DocumentImpl() : root(0) {} + DocumentImpl() : root(0) { } virtual ~DocumentImpl() { if (root) D(root); } @@ -242,6 +242,22 @@ public: class Element : public Node { public: + // C++ API + static QScriptValue prototype(QScriptEngine *); +}; + +class Attr : public Node +{ +public: + // JS API + static QScriptValue name(QScriptContext *context, QScriptEngine *engine); + static QScriptValue specified(QScriptContext *context, QScriptEngine *engine); + static QScriptValue value(QScriptContext *context, QScriptEngine *engine); + static QScriptValue ownerElement(QScriptContext *context, QScriptEngine *engine); + static QScriptValue schemaTypeInfo(QScriptContext *context, QScriptEngine *engine); + static QScriptValue isId(QScriptContext *context, QScriptEngine *engine); + + // C++ API static QScriptValue prototype(QScriptEngine *); }; @@ -308,6 +324,7 @@ QScriptValue Node::nodeName(QScriptContext *context, QScriptEngine *engine) { Node node = qscriptvalue_cast<Node>(context->thisObject()); if (node.isNull()) return engine->undefinedValue(); + return QScriptValue(node.d->name); } @@ -316,6 +333,15 @@ QScriptValue Node::nodeValue(QScriptContext *context, QScriptEngine *engine) Node node = qscriptvalue_cast<Node>(context->thisObject()); if (node.isNull()) return engine->undefinedValue(); + if (node.d->type == NodeImpl::Document || + node.d->type == NodeImpl::DocumentFragment || + node.d->type == NodeImpl::DocumentType || + node.d->type == NodeImpl::Element || + node.d->type == NodeImpl::Entity || + node.d->type == NodeImpl::EntityReference || + node.d->type == NodeImpl::Notation) + return engine->nullValue(); + return QScriptValue(node.d->data); } @@ -430,6 +456,8 @@ QScriptValue Node::create(QScriptEngine *engine, NodeImpl *data) switch (data->type) { case NodeImpl::Attr: + instance.setPrototype(Attr::prototype(engine)); + break; case NodeImpl::Comment: case NodeImpl::Document: case NodeImpl::DocumentFragment: @@ -468,6 +496,42 @@ QScriptValue Element::prototype(QScriptEngine *engine) return proto; } +QScriptValue Attr::prototype(QScriptEngine *engine) +{ + QScriptValue proto = engine->newObject(); + proto.setPrototype(Node::prototype(engine)); + + proto.setProperty(QLatin1String("name"), engine->newFunction(name), QScriptValue::ReadOnly | QScriptValue::PropertyGetter); + proto.setProperty(QLatin1String("value"), engine->newFunction(value), QScriptValue::ReadOnly | QScriptValue::PropertyGetter); + proto.setProperty(QLatin1String("ownerElement"), engine->newFunction(ownerElement), QScriptValue::ReadOnly | QScriptValue::PropertyGetter); + + return proto; +} + +QScriptValue Attr::name(QScriptContext *context, QScriptEngine *engine) +{ + Node node = qscriptvalue_cast<Node>(context->thisObject()); + if (node.isNull()) return engine->undefinedValue(); + + return QScriptValue(node.d->name); +} + +QScriptValue Attr::value(QScriptContext *context, QScriptEngine *engine) +{ + Node node = qscriptvalue_cast<Node>(context->thisObject()); + if (node.isNull()) return engine->undefinedValue(); + + return QScriptValue(node.d->data); +} + +QScriptValue Attr::ownerElement(QScriptContext *context, QScriptEngine *engine) +{ + Node node = qscriptvalue_cast<Node>(context->thisObject()); + if (node.isNull()) return engine->undefinedValue(); + + return Node::create(engine, node.d->parent); +} + QScriptValue CharacterData::length(QScriptContext *context, QScriptEngine *engine) { Node node = qscriptvalue_cast<Node>(context->thisObject()); @@ -581,6 +645,7 @@ QScriptValue Document::load(QScriptEngine *engine, const QString &data) attr->namespaceUri = a.namespaceUri().toString(); attr->name = a.name().toString(); attr->data = a.value().toString(); + attr->parent = node; node->attributes.append(attr); } } @@ -800,17 +865,29 @@ NamedNodeMapClass::QueryFlags NamedNodeMapClass::queryProperty(const QScriptValu if (!(flags & HandlesReadAccess)) return 0; - bool ok = false; - uint index = name.toString().toUInt(&ok); - if (!ok) + NamedNodeMap map = qscriptvalue_cast<NamedNodeMap>(object.data()); + if (map.isNull()) return 0; - NamedNodeMap map = qscriptvalue_cast<NamedNodeMap>(object.data()); - if (map.isNull() || (uint)map.list->count() <= index) - return 0; // ### I think we're meant to raise an exception + bool ok = false; + QString nameString = name.toString(); + uint index = nameString.toUInt(&ok); + if (ok) { + if ((uint)map.list->count() <= index) + return 0; + + *id = index; + return HandlesReadAccess; + } else { + for (int ii = 0; ii < map.list->count(); ++ii) { + if (map.list->at(ii) && map.list->at(ii)->name == nameString) { + *id = ii; + return HandlesReadAccess; + } + } + } - *id = index; - return HandlesReadAccess; + return 0; } QScriptValue NamedNodeMapClass::property(const QScriptValue &object, const QScriptString &, uint id) @@ -1050,7 +1127,7 @@ void QmlXMLHttpRequest::addHeader(const QString &name, const QString &value) QString QmlXMLHttpRequest::header(const QString &name) { - QByteArray utfname = name.toUtf8(); + QByteArray utfname = name.toLower().toUtf8(); foreach (const HeaderPair &header, m_headersList) { if (header.first == utfname) @@ -1079,7 +1156,11 @@ void QmlXMLHttpRequest::fillHeadersList() m_headersList.clear(); foreach (const QByteArray &header, headerList) { - HeaderPair pair (header, m_network->rawHeader(header)); + HeaderPair pair (header.toLower(), m_network->rawHeader(header)); + if (pair.first == "set-cookie" || + pair.first == "set-cookie2") + continue; + m_headersList << pair; } } @@ -1190,11 +1271,19 @@ void QmlXMLHttpRequest::error(QNetworkReply::NetworkError error) QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray()); m_responseEntityBody = QByteArray(); - m_errorFlag = true; - m_request = QNetworkRequest(); + m_request = QNetworkRequest(); destroyNetwork(); + if (error != QNetworkReply::ContentAccessDenied && + error != QNetworkReply::ContentOperationNotPermittedError && + error != QNetworkReply::ContentNotFoundError) { + m_errorFlag = true; + } else { + m_state = Loading; + dispatchCallback(); + } + m_state = Done; dispatchCallback(); } diff --git a/tests/auto/declarative/xmlhttprequest/data/abort.expect b/tests/auto/declarative/xmlhttprequest/data/abort.expect new file mode 100644 index 0000000..5cdc24e --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/abort.expect @@ -0,0 +1,10 @@ +PUT /testdocument.html HTTP/1.1 +Content-Type: text/plain;charset=UTF-8 +Content-Length: 9 +Connection: Keep-Alive +Accept-Encoding: gzip +accept-language: en,* +User-Agent: Mozilla/5.0 +Host: localhost:14445 + +Test Data
\ No newline at end of file diff --git a/tests/auto/declarative/xmlhttprequest/data/abort.qml b/tests/auto/declarative/xmlhttprequest/data/abort.qml new file mode 100644 index 0000000..132eb96 --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/abort.qml @@ -0,0 +1,42 @@ +import Qt 4.6 + +Object { + property string urlDummy + property string url + + property bool seenDone: false + property bool didNotSeeUnsent: true + property bool endStateUnsent: false + property bool dataOK: false + + Component.onCompleted: { + var x = new XMLHttpRequest; + x.open("GET", urlDummy); + x.setRequestHeader("Test-header", "TestValue"); + x.send(); + + x.onreadystatechange = function() { + if (x.readyState == XMLHttpRequest.DONE) { + seenDone = true; + } else if (x.readyState == XMLHttpRequest.UNSENT) { + didNotSeeUnsent = false; + } + } + + x.abort(); + + if (x.readyState == XMLHttpRequest.UNSENT) { + endStateUnsent = true; + } + + x.onreadystatechange = function() { + if (x.readyState == XMLHttpRequest.DONE) { + dataOK = (x.responseText == "QML Rocks!\n"); + } + } + x.open("PUT", url); + x.send("Test Data"); + } +} + + diff --git a/tests/auto/declarative/xmlhttprequest/data/abort.reply b/tests/auto/declarative/xmlhttprequest/data/abort.reply new file mode 100644 index 0000000..35b11f4 --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/abort.reply @@ -0,0 +1,2 @@ +HTTP/1.0 200 OK +Content-type: text/html; charset=UTF-8 diff --git a/tests/auto/declarative/xmlhttprequest/data/abort_opened.qml b/tests/auto/declarative/xmlhttprequest/data/abort_opened.qml new file mode 100644 index 0000000..9c7449f --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/abort_opened.qml @@ -0,0 +1,58 @@ +import Qt 4.6 + +Object { + property string url: "testdocument.html" + + property bool readyState: false + property bool openedState: false + + property bool status: false + property bool statusText: false + property bool responseText: false + property bool responseXML: false + + property bool dataOK: false + + Component.onCompleted: { + var x = new XMLHttpRequest; + x.abort(); + + if (x.readyState == XMLHttpRequest.UNSENT) + readyState = true; + + x.open("PUT", url); + + x.abort(); + + x.open("GET", url); + + if (x.readyState == XMLHttpRequest.OPENED) + openedState = true; + + try { + var a = x.status; + } catch (error) { + if (error.code == DOMException.INVALID_STATE_ERR) + status = true; + } + try { + var a = x.statusText; + } catch (error) { + if (error.code == DOMException.INVALID_STATE_ERR) + statusText = true; + } + responseText = (x.responseText == ""); + responseXML = (x.responseXML == null); + + // Test to the end + x.onreadystatechange = function() { + if (x.readyState == XMLHttpRequest.DONE) { + dataOK = (x.responseText == "QML Rocks!\n"); + } + } + + + x.send() + } +} + diff --git a/tests/auto/declarative/xmlhttprequest/data/abort_unsent.qml b/tests/auto/declarative/xmlhttprequest/data/abort_unsent.qml new file mode 100644 index 0000000..4bc479e --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/abort_unsent.qml @@ -0,0 +1,54 @@ +import Qt 4.6 + +Object { + property string url: "testdocument.html" + + property bool readyState: false + property bool openedState: false + + property bool status: false + property bool statusText: false + property bool responseText: false + property bool responseXML: false + + property bool dataOK: false + + Component.onCompleted: { + var x = new XMLHttpRequest; + x.abort(); + + if (x.readyState == XMLHttpRequest.UNSENT) + readyState = true; + + x.open("GET", url); + + if (x.readyState == XMLHttpRequest.OPENED) + openedState = true; + + try { + var a = x.status; + } catch (error) { + if (error.code == DOMException.INVALID_STATE_ERR) + status = true; + } + try { + var a = x.statusText; + } catch (error) { + if (error.code == DOMException.INVALID_STATE_ERR) + statusText = true; + } + responseText = (x.responseText == ""); + responseXML = (x.responseXML == null); + + // Test to the end + x.onreadystatechange = function() { + if (x.readyState == XMLHttpRequest.DONE) { + dataOK = (x.responseText == "QML Rocks!\n"); + } + } + + + x.send() + } +} + diff --git a/tests/auto/declarative/xmlhttprequest/data/attr.qml b/tests/auto/declarative/xmlhttprequest/data/attr.qml new file mode 100644 index 0000000..d0ee720 --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/attr.qml @@ -0,0 +1,80 @@ +import Qt 4.6 + +Object { + property bool xmlTest: false + property bool dataOK: false + + Script { + function checkAttr(documentElement, attr) + { + if (attr == null) + return; + + if (attr.name != "attr") + return; + + if (attr.value != "myvalue") + return; + + if (attr.ownerElement.tagName != documentElement.tagName) + return; + + if (attr.nodeName != "attr") + return; + + if (attr.nodeValue != "myvalue") + return; + + if (attr.nodeType != 2) + return; + + if (attr.childNodes.length != 0) + return; + + if (attr.firstChild != null) + return; + + if (attr.lastChild != null) + return; + + if (attr.previousSibling != null) + return; + + if (attr.nextSibling != null) + return; + + if (attr.attributes != null) + return; + + xmlTest = true; + } + + function checkXML(document) + { + checkAttr(document.documentElement, document.documentElement.attributes[0]); + } + } + + Component.onCompleted: { + var x = new XMLHttpRequest; + + x.open("GET", "attr.xml"); + + // Test to the end + x.onreadystatechange = function() { + if (x.readyState == XMLHttpRequest.DONE) { + + dataOK = true; + + if (x.responseXML != null) + checkXML(x.responseXML); + + } + } + + x.send() + } +} + + + diff --git a/tests/auto/declarative/xmlhttprequest/data/attr.xml b/tests/auto/declarative/xmlhttprequest/data/attr.xml new file mode 100644 index 0000000..2aa64a3 --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/attr.xml @@ -0,0 +1 @@ +<root attr="myvalue" /> diff --git a/tests/auto/declarative/xmlhttprequest/data/document.qml b/tests/auto/declarative/xmlhttprequest/data/document.qml new file mode 100644 index 0000000..fe78e31 --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/document.qml @@ -0,0 +1,49 @@ +import Qt 4.6 + +Object { + property bool xmlTest: false + property bool dataOK: false + + Script { + function checkXML(document) + { + if (document.xmlVersion != "1.0") + return; + + if (document.xmlStandalone != true) + return; + + if (document.documentElement == null) + return; + + if (document.nodeValue != null) + return; + + // ### Test other node properties + // ### test encoding (what is a valid qt encoding?) + xmlTest = true; + } + } + + Component.onCompleted: { + var x = new XMLHttpRequest; + + x.open("GET", "document.xml"); + + // Test to the end + x.onreadystatechange = function() { + if (x.readyState == XMLHttpRequest.DONE) { + + dataOK = true; + + if (x.responseXML != null) + checkXML(x.responseXML); + + } + } + + x.send() + } +} + + diff --git a/tests/auto/declarative/xmlhttprequest/data/document.xml b/tests/auto/declarative/xmlhttprequest/data/document.xml new file mode 100644 index 0000000..b5fbe31 --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/document.xml @@ -0,0 +1,3 @@ +<?xml version="1.0" standalone='yes' ?> +<root> +</root> diff --git a/tests/auto/declarative/xmlhttprequest/data/element.qml b/tests/auto/declarative/xmlhttprequest/data/element.qml new file mode 100644 index 0000000..a1ae2ab --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/element.qml @@ -0,0 +1,101 @@ +import Qt 4.6 + +Object { + property bool xmlTest: false + property bool dataOK: false + + Script { + function checkElement(e) + { + if (e.tagName != "root") + return; + + if (e.nodeName != "root") + return; + + if (e.nodeValue != null) + return; + + if (e.nodeType != 1) + return; + + var childTagNames = [ "person", "fruit" ]; + + if (e.childNodes.length != childTagNames.length) + return; + + for (var ii = 0; ii < childTagNames.length; ++ii) { + if (e.childNodes[ii].tagName != childTagNames[ii]) + return; + } + + if (e.childNodes[childTagNames.length + 1] != null) + return; + + if (e.firstChild.tagName != e.childNodes[0].tagName) + return; + + if (e.lastChild.tagName != e.childNodes[1].tagName) + return; + + if (e.previousSibling != null) + return; + + if (e.nextSibling != null) + return; + + if (e.attributes == null) + return; + + var attr1 = e.attributes["attr"]; + if (attr1.nodeValue != "value") + return; + + var attrIdx = e.attributes[0]; + if (attrIdx.nodeValue != "value") + return; + + var attr2 = e.attributes["attr2"]; + if (attr2.nodeValue != "value2") + return; + + var attr3 = e.attributes["attr3"]; + if (attr3 != null) + return; + + var attrIdx2 = e.attributes[11]; + if (attrIdx2 != null) + return; + + xmlTest = true; + } + + function checkXML(document) + { + checkElement(document.documentElement); + } + } + + Component.onCompleted: { + var x = new XMLHttpRequest; + + x.open("GET", "element.xml"); + + // Test to the end + x.onreadystatechange = function() { + if (x.readyState == XMLHttpRequest.DONE) { + + dataOK = true; + + if (x.responseXML != null) + checkXML(x.responseXML); + + } + } + + x.send() + } +} + + + diff --git a/tests/auto/declarative/xmlhttprequest/data/element.xml b/tests/auto/declarative/xmlhttprequest/data/element.xml new file mode 100644 index 0000000..071ffae --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/element.xml @@ -0,0 +1 @@ +<root attr="value" attr2="value2"><person /><fruit /></root> diff --git a/tests/auto/declarative/xmlhttprequest/data/getAllResponseHeaders.qml b/tests/auto/declarative/xmlhttprequest/data/getAllResponseHeaders.qml new file mode 100644 index 0000000..0bee7ad --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/getAllResponseHeaders.qml @@ -0,0 +1,65 @@ +import Qt 4.6 + +Object { + property string url + + property bool unsentException: false + property bool openedException: false + + property bool readyState: false + property bool openedState: false + + property bool headersReceivedState: false + property bool headersReceivedHeader: false + + property bool doneState: false + property bool doneHeader: false + + property bool dataOK: false + + Component.onCompleted: { + var x = new XMLHttpRequest; + + try { + x.getResponseHeader("Test-Header"); + } catch (e) { + if (e.code == DOMException.INVALID_STATE_ERR) + unsentException = true; + } + + if (x.readyState == XMLHttpRequest.UNSENT) + readyState = true; + + x.open("GET", url); + + if (x.readyState == XMLHttpRequest.OPENED) + openedState = true; + + try { + x.getResponseHeader("Test-Header"); + } catch (e) { + if (e.code == DOMException.INVALID_STATE_ERR) + openedException = true; + } + + var headers = "content-type: text/html; charset=UTF-8\r\ntest-header: TestValue\r\nmultitest-header: TestValue, SecondTestValue\r\ncontent-length: 11"; + + // Test to the end + x.onreadystatechange = function() { + if (x.readyState == XMLHttpRequest.HEADERS_RECEIVED) { + headersReceivedState = true; + + headersReceivedHeader = (x.getAllResponseHeaders() == headers); + } else if (x.readyState == XMLHttpRequest.DONE) { + doneState = headersReceivedState && true; + + doneHeader = (x.getAllResponseHeaders() == headers); + dataOK = (x.responseText == "QML Rocks!\n"); + } + } + + x.send() + } +} + + diff --git a/tests/auto/declarative/xmlhttprequest/data/getResponseHeader.expect b/tests/auto/declarative/xmlhttprequest/data/getResponseHeader.expect new file mode 100644 index 0000000..40e648e --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/getResponseHeader.expect @@ -0,0 +1,7 @@ +GET /testdocument.html HTTP/1.1 +Connection: Keep-Alive +Accept-Encoding: gzip +accept-language: en,* +User-Agent: Mozilla/5.0 +Host: localhost:14445 + diff --git a/tests/auto/declarative/xmlhttprequest/data/getResponseHeader.qml b/tests/auto/declarative/xmlhttprequest/data/getResponseHeader.qml new file mode 100644 index 0000000..798b346 --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/getResponseHeader.qml @@ -0,0 +1,75 @@ +import Qt 4.6 + +Object { + property string url + + property bool unsentException: false + property bool openedException: false + + property bool readyState: false + property bool openedState: false + + property bool headersReceivedState: false + property bool headersReceivedNullHeader: false + property bool headersReceivedValidHeader: false + property bool headersReceivedMultiValidHeader: false + property bool headersReceivedCookieHeader: false + + property bool doneState: false + property bool doneNullHeader: false + property bool doneValidHeader: false + property bool doneMultiValidHeader: false + property bool doneCookieHeader: false + + property bool dataOK: false + + Component.onCompleted: { + var x = new XMLHttpRequest; + + try { + x.getResponseHeader("Test-Header"); + } catch (e) { + if (e.code == DOMException.INVALID_STATE_ERR) + unsentException = true; + } + + if (x.readyState == XMLHttpRequest.UNSENT) + readyState = true; + + x.open("GET", url); + + if (x.readyState == XMLHttpRequest.OPENED) + openedState = true; + + try { + x.getResponseHeader("Test-Header"); + } catch (e) { + if (e.code == DOMException.INVALID_STATE_ERR) + openedException = true; + } + + // Test to the end + x.onreadystatechange = function() { + if (x.readyState == XMLHttpRequest.HEADERS_RECEIVED) { + headersReceivedState = true; + + headersReceivedNullHeader = (x.getResponseHeader("Nonexistant-header") == ""); + headersReceivedValidHeader = (x.getResponseHeader("Test-HEAder") == "TestValue"); + headersReceivedMultiValidHeader = (x.getResponseHeader("MultiTest-HEAder") == "TestValue, SecondTestValue"); + headersReceivedCookieHeader = (x.getResponseHeader("Set-Cookie") == "" && x.getResponseHeader("Set-Cookie2") == ""); + } else if (x.readyState == XMLHttpRequest.DONE) { + doneState = headersReceivedState && true; + + doneNullHeader = (x.getResponseHeader("Nonexistant-header") == ""); + doneValidHeader = (x.getResponseHeader("Test-HEAder") == "TestValue"); + doneMultiValidHeader = (x.getResponseHeader("MultiTest-HEAder") == "TestValue, SecondTestValue"); + doneCookieHeader = (x.getResponseHeader("Set-Cookie") == "" && x.getResponseHeader("Set-Cookie2") == ""); + dataOK = (x.responseText == "QML Rocks!\n"); + } + } + + x.send() + } +} + + diff --git a/tests/auto/declarative/xmlhttprequest/data/getResponseHeader.reply b/tests/auto/declarative/xmlhttprequest/data/getResponseHeader.reply new file mode 100644 index 0000000..62ec67b --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/getResponseHeader.reply @@ -0,0 +1,7 @@ +HTTP/1.0 200 OK +Content-type: text/html; charset=UTF-8 +Test-Header: TestValue +MultiTest-Header: TestValue +MultiTest-Header: SecondTestValue +Set-Cookie: mycook=Value +Set-Cookie2: mycook=Value diff --git a/tests/auto/declarative/xmlhttprequest/data/responseText.qml b/tests/auto/declarative/xmlhttprequest/data/responseText.qml new file mode 100644 index 0000000..0bb8659 --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/responseText.qml @@ -0,0 +1,52 @@ +import Qt 4.6 + +Object { + property string url + property string expectedText + + property bool unsent: false + property bool opened: false + property bool sent: false + property bool headersReceived: false + + property bool loading: false + property bool done: false + + property bool reset: false + + property bool dataOK: false + + Component.onCompleted: { + var x = new XMLHttpRequest; + + unsent = (x.responseText == ""); + + x.open("GET", url); + + opened = (x.responseText == ""); + + // Test to the end + x.onreadystatechange = function() { + if (x.readyState == XMLHttpRequest.HEADERS_RECEIVED) { + headersReceived = (x.responseText == ""); + } else if (x.readyState == XMLHttpRequest.LOADING) { + if (x.responseText == expectedText) + loading = true; + } else if (x.readyState == XMLHttpRequest.DONE) { + if (x.responseText == expectedText) + done = true; + + dataOK = (x.responseText == expectedText); + + x.open("GET", url); + + reset = (x.responseText == ""); + } + } + + x.send() + + sent = (x.responseText == ""); + } +} + diff --git a/tests/auto/declarative/xmlhttprequest/data/responseXML_invalid.qml b/tests/auto/declarative/xmlhttprequest/data/responseXML_invalid.qml new file mode 100644 index 0000000..4fc4fe5 --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/responseXML_invalid.qml @@ -0,0 +1,24 @@ +import Qt 4.6 + +Object { + property bool xmlNull: false + property bool dataOK: false + + Component.onCompleted: { + var x = new XMLHttpRequest; + + x.open("GET", "testdocument.html"); + + // Test to the end + x.onreadystatechange = function() { + if (x.readyState == XMLHttpRequest.DONE) { + dataOK = (x.responseText == "QML Rocks!\n"); + xmlNull = (x.responseXML == null); + } + } + + + x.send() + } +} + diff --git a/tests/auto/declarative/xmlhttprequest/data/status.200.reply b/tests/auto/declarative/xmlhttprequest/data/status.200.reply new file mode 100644 index 0000000..35b11f4 --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/status.200.reply @@ -0,0 +1,2 @@ +HTTP/1.0 200 OK +Content-type: text/html; charset=UTF-8 diff --git a/tests/auto/declarative/xmlhttprequest/data/status.404.reply b/tests/auto/declarative/xmlhttprequest/data/status.404.reply new file mode 100644 index 0000000..964a7a8 --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/status.404.reply @@ -0,0 +1,2 @@ +HTTP/1.0 404 Document not found +Content-type: text/html; charset=UTF-8 diff --git a/tests/auto/declarative/xmlhttprequest/data/status.expect b/tests/auto/declarative/xmlhttprequest/data/status.expect new file mode 100644 index 0000000..40e648e --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/status.expect @@ -0,0 +1,7 @@ +GET /testdocument.html HTTP/1.1 +Connection: Keep-Alive +Accept-Encoding: gzip +accept-language: en,* +User-Agent: Mozilla/5.0 +Host: localhost:14445 + diff --git a/tests/auto/declarative/xmlhttprequest/data/status.qml b/tests/auto/declarative/xmlhttprequest/data/status.qml new file mode 100644 index 0000000..7b2e8d0 --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/status.qml @@ -0,0 +1,77 @@ +import Qt 4.6 + +Object { + property string url + property int expectedStatus + + property bool unsentException: false; + property bool openedException: false; + property bool sentException: false; + + property bool headersReceived: false + property bool loading: false + property bool done: false + + property bool resetException: false + + property bool dataOK: false + + Component.onCompleted: { + var x = new XMLHttpRequest; + + try { + var a = x.status; + } catch (e) { + if (e.code == DOMException.INVALID_STATE_ERR) + unsentException = true; + } + + x.open("GET", url); + + try { + var a = x.status; + } catch (e) { + if (e.code == DOMException.INVALID_STATE_ERR) + openedException = true; + } + + // Test to the end + x.onreadystatechange = function() { + if (x.readyState == XMLHttpRequest.HEADERS_RECEIVED) { + if (x.status == expectedStatus) + headersReceived = true; + } else if (x.readyState == XMLHttpRequest.LOADING) { + if (x.status == expectedStatus) + loading = true; + } else if (x.readyState == XMLHttpRequest.DONE) { + if (x.status == expectedStatus) + done = true; + + if (expectedStatus == 404) { + dataOK = (x.responseText == ""); + } else { + dataOK = (x.responseText == "QML Rocks!\n"); + } + + x.open("GET", url); + + try { + var a = x.status; + } catch (e) { + if (e.code == DOMException.INVALID_STATE_ERR) + resetException = true; + } + + } + } + + x.send() + + try { + var a = x.status; + } catch (e) { + if (e.code == DOMException.INVALID_STATE_ERR) + sentException = true; + } + } +} diff --git a/tests/auto/declarative/xmlhttprequest/data/statusText.qml b/tests/auto/declarative/xmlhttprequest/data/statusText.qml new file mode 100644 index 0000000..00d8fdc --- /dev/null +++ b/tests/auto/declarative/xmlhttprequest/data/statusText.qml @@ -0,0 +1,77 @@ +import Qt 4.6 + +Object { + property string url + property string expectedStatus + + property bool unsentException: false; + property bool openedException: false; + property bool sentException: false; + + property bool headersReceived: false + property bool loading: false + property bool done: false + + property bool resetException: false + + property bool dataOK: false + + Component.onCompleted: { + var x = new XMLHttpRequest; + + try { + var a = x.statusText; + } catch (e) { + if (e.code == DOMException.INVALID_STATE_ERR) + unsentException = true; + } + + x.open("GET", url); + + try { + var a = x.statusText; + } catch (e) { + if (e.code == DOMException.INVALID_STATE_ERR) + openedException = true; + } + + // Test to the end + x.onreadystatechange = function() { + if (x.readyState == XMLHttpRequest.HEADERS_RECEIVED) { + if (x.statusText == expectedStatus) + headersReceived = true; + } else if (x.readyState == XMLHttpRequest.LOADING) { + if (x.statusText == expectedStatus) + loading = true; + } else if (x.readyState == XMLHttpRequest.DONE) { + if (x.statusText == expectedStatus) + done = true; + + if (expectedStatus != "OK") { + dataOK = (x.responseText == ""); + } else { + dataOK = (x.responseText == "QML Rocks!\n"); + } + + x.open("GET", url); + + try { + var a = x.statusText; + } catch (e) { + if (e.code == DOMException.INVALID_STATE_ERR) + resetException = true; + } + + } + } + + x.send() + + try { + var a = x.statusText; + } catch (e) { + if (e.code == DOMException.INVALID_STATE_ERR) + sentException = true; + } + } +} diff --git a/tests/auto/declarative/xmlhttprequest/testhttpserver.cpp b/tests/auto/declarative/xmlhttprequest/testhttpserver.cpp index b579944..b464a1b 100644 --- a/tests/auto/declarative/xmlhttprequest/testhttpserver.cpp +++ b/tests/auto/declarative/xmlhttprequest/testhttpserver.cpp @@ -68,8 +68,9 @@ bool TestHTTPServer::wait(const QUrl &expect, const QUrl &reply, const QUrl &bod if (!replyFile.open(QIODevice::ReadOnly)) return false; bodyData = QByteArray(); - QFile bodyFile(body.toLocalFile()); - if (bodyFile.open(QIODevice::ReadOnly)) { + if (body.isValid()) { + QFile bodyFile(body.toLocalFile()); + if (!bodyFile.open(QIODevice::ReadOnly)) return false; bodyData = bodyFile.readAll(); } diff --git a/tests/auto/declarative/xmlhttprequest/tst_xmlhttprequest.cpp b/tests/auto/declarative/xmlhttprequest/tst_xmlhttprequest.cpp index bedb620..5a1955e 100644 --- a/tests/auto/declarative/xmlhttprequest/tst_xmlhttprequest.cpp +++ b/tests/auto/declarative/xmlhttprequest/tst_xmlhttprequest.cpp @@ -45,6 +45,7 @@ #include <QDebug> #include <QWebPage> #include <QWebFrame> +#include <QNetworkCookieJar> #include "testhttpserver.h" #define SERVER_PORT 14445 @@ -75,10 +76,25 @@ private slots: void send_ignoreData(); void send_withdata(); void abort(); + void abort_unsent(); + void abort_opened(); + void getResponseHeader(); + void getAllResponseHeaders(); + void status(); + void statusText(); + void responseText(); + void responseXML_invalid(); + + void document(); + void element(); + void attr(); // Crashes // void outstanding_request_at_shutdown(); + // void network_errors() + // void readyState() + private: QmlEngine engine; }; @@ -610,8 +626,395 @@ void tst_xmlhttprequest::send_withdata() } } +// Test abort() has no effect in unsent state +void tst_xmlhttprequest::abort_unsent() +{ + QmlComponent component(&engine, TEST_FILE("abort_unsent.qml")); + QObject *object = component.beginCreate(engine.rootContext()); + QVERIFY(object != 0); + object->setProperty("url", "testdocument.html"); + component.completeCreate(); + + QCOMPARE(object->property("readyState").toBool(), true); + QCOMPARE(object->property("openedState").toBool(), true); + QCOMPARE(object->property("status").toBool(), true); + QCOMPARE(object->property("statusText").toBool(), true); + QCOMPARE(object->property("responseText").toBool(), true); + QCOMPARE(object->property("responseXML").toBool(), true); + + TRY_WAIT(object->property("dataOK").toBool() == true); + + delete object; +} + +// Test abort() cancels an open (but unsent) request +void tst_xmlhttprequest::abort_opened() +{ + QmlComponent component(&engine, TEST_FILE("abort_opened.qml")); + QObject *object = component.beginCreate(engine.rootContext()); + QVERIFY(object != 0); + object->setProperty("url", "testdocument.html"); + component.completeCreate(); + + QCOMPARE(object->property("readyState").toBool(), true); + QCOMPARE(object->property("openedState").toBool(), true); + QCOMPARE(object->property("status").toBool(), true); + QCOMPARE(object->property("statusText").toBool(), true); + QCOMPARE(object->property("responseText").toBool(), true); + QCOMPARE(object->property("responseXML").toBool(), true); + + TRY_WAIT(object->property("dataOK").toBool() == true); + + delete object; +} + +// Test abort() aborts in progress send void tst_xmlhttprequest::abort() { + TestHTTPServer server(SERVER_PORT); + QVERIFY(server.isValid()); + QVERIFY(server.wait(TEST_FILE("abort.expect"), + TEST_FILE("abort.reply"), + TEST_FILE("testdocument.html"))); + + QmlComponent component(&engine, TEST_FILE("abort.qml")); + QObject *object = component.beginCreate(engine.rootContext()); + QVERIFY(object != 0); + object->setProperty("urlDummy", "http://localhost:14449/testdocument.html"); + object->setProperty("url", "http://localhost:14445/testdocument.html"); + component.completeCreate(); + + QCOMPARE(object->property("seenDone").toBool(), true); + QCOMPARE(object->property("didNotSeeUnsent").toBool(), true); + QCOMPARE(object->property("endStateUnsent").toBool(), true); + + TRY_WAIT(object->property("dataOK").toBool() == true); + + delete object; +} + +void tst_xmlhttprequest::getResponseHeader() +{ + QmlEngine engine; // Avoid cookie contamination + + TestHTTPServer server(SERVER_PORT); + QVERIFY(server.isValid()); + QVERIFY(server.wait(TEST_FILE("getResponseHeader.expect"), + TEST_FILE("getResponseHeader.reply"), + TEST_FILE("testdocument.html"))); + + + QmlComponent component(&engine, TEST_FILE("getResponseHeader.qml")); + QObject *object = component.beginCreate(engine.rootContext()); + QVERIFY(object != 0); + object->setProperty("url", "http://localhost:14445/testdocument.html"); + component.completeCreate(); + + QCOMPARE(object->property("unsentException").toBool(), true); + QCOMPARE(object->property("openedException").toBool(), true); + QCOMPARE(object->property("readyState").toBool(), true); + QCOMPARE(object->property("openedState").toBool(), true); + + TRY_WAIT(object->property("dataOK").toBool() == true); + + QCOMPARE(object->property("headersReceivedState").toBool(), true); + QCOMPARE(object->property("headersReceivedNullHeader").toBool(), true); + QCOMPARE(object->property("headersReceivedValidHeader").toBool(), true); + QCOMPARE(object->property("headersReceivedMultiValidHeader").toBool(), true); + QCOMPARE(object->property("headersReceivedCookieHeader").toBool(), true); + + QCOMPARE(object->property("doneState").toBool(), true); + QCOMPARE(object->property("doneNullHeader").toBool(), true); + QCOMPARE(object->property("doneValidHeader").toBool(), true); + QCOMPARE(object->property("doneMultiValidHeader").toBool(), true); + QCOMPARE(object->property("doneCookieHeader").toBool(), true); + + delete object; +} + +void tst_xmlhttprequest::getAllResponseHeaders() +{ + QmlEngine engine; // Avoid cookie contamination + + TestHTTPServer server(SERVER_PORT); + QVERIFY(server.isValid()); + QVERIFY(server.wait(TEST_FILE("getResponseHeader.expect"), + TEST_FILE("getResponseHeader.reply"), + TEST_FILE("testdocument.html"))); + + QmlComponent component(&engine, TEST_FILE("getAllResponseHeaders.qml")); + QObject *object = component.beginCreate(engine.rootContext()); + QVERIFY(object != 0); + object->setProperty("url", "http://localhost:14445/testdocument.html"); + component.completeCreate(); + + QCOMPARE(object->property("unsentException").toBool(), true); + QCOMPARE(object->property("openedException").toBool(), true); + QCOMPARE(object->property("readyState").toBool(), true); + QCOMPARE(object->property("openedState").toBool(), true); + + TRY_WAIT(object->property("dataOK").toBool() == true); + + QCOMPARE(object->property("headersReceivedState").toBool(), true); + QCOMPARE(object->property("headersReceivedHeader").toBool(), true); + + QCOMPARE(object->property("doneState").toBool(), true); + QCOMPARE(object->property("doneHeader").toBool(), true); + + delete object; +} + +void tst_xmlhttprequest::status() +{ + { + TestHTTPServer server(SERVER_PORT); + QVERIFY(server.isValid()); + QVERIFY(server.wait(TEST_FILE("status.expect"), + TEST_FILE("status.200.reply"), + TEST_FILE("testdocument.html"))); + + QmlComponent component(&engine, TEST_FILE("status.qml")); + QObject *object = component.beginCreate(engine.rootContext()); + QVERIFY(object != 0); + object->setProperty("url", "http://localhost:14445/testdocument.html"); + object->setProperty("expectedStatus", 200); + component.completeCreate(); + + TRY_WAIT(object->property("dataOK").toBool() == true); + + QCOMPARE(object->property("unsentException").toBool(), true); + QCOMPARE(object->property("openedException").toBool(), true); + QCOMPARE(object->property("sentException").toBool(), true); + QCOMPARE(object->property("headersReceived").toBool(), true); + QCOMPARE(object->property("loading").toBool(), true); + QCOMPARE(object->property("done").toBool(), true); + QCOMPARE(object->property("resetException").toBool(), true); + + delete object; + } + + { + TestHTTPServer server(SERVER_PORT); + QVERIFY(server.isValid()); + QVERIFY(server.wait(TEST_FILE("status.expect"), + TEST_FILE("status.404.reply"), + TEST_FILE("testdocument.html"))); + + QmlComponent component(&engine, TEST_FILE("status.qml")); + QObject *object = component.beginCreate(engine.rootContext()); + QVERIFY(object != 0); + object->setProperty("url", "http://localhost:14445/testdocument.html"); + object->setProperty("expectedStatus", 404); + component.completeCreate(); + + TRY_WAIT(object->property("dataOK").toBool() == true); + + QCOMPARE(object->property("unsentException").toBool(), true); + QCOMPARE(object->property("openedException").toBool(), true); + QCOMPARE(object->property("sentException").toBool(), true); + QCOMPARE(object->property("headersReceived").toBool(), true); + QCOMPARE(object->property("loading").toBool(), true); + QCOMPARE(object->property("done").toBool(), true); + QCOMPARE(object->property("resetException").toBool(), true); + + delete object; + } +} + +void tst_xmlhttprequest::statusText() +{ + { + TestHTTPServer server(SERVER_PORT); + QVERIFY(server.isValid()); + QVERIFY(server.wait(TEST_FILE("status.expect"), + TEST_FILE("status.200.reply"), + TEST_FILE("testdocument.html"))); + + QmlComponent component(&engine, TEST_FILE("statusText.qml")); + QObject *object = component.beginCreate(engine.rootContext()); + QVERIFY(object != 0); + object->setProperty("url", "http://localhost:14445/testdocument.html"); + object->setProperty("expectedStatus", "OK"); + component.completeCreate(); + + TRY_WAIT(object->property("dataOK").toBool() == true); + + QCOMPARE(object->property("unsentException").toBool(), true); + QCOMPARE(object->property("openedException").toBool(), true); + QCOMPARE(object->property("sentException").toBool(), true); + QCOMPARE(object->property("headersReceived").toBool(), true); + QCOMPARE(object->property("loading").toBool(), true); + QCOMPARE(object->property("done").toBool(), true); + QCOMPARE(object->property("resetException").toBool(), true); + + delete object; + } + + { + TestHTTPServer server(SERVER_PORT); + QVERIFY(server.isValid()); + QVERIFY(server.wait(TEST_FILE("status.expect"), + TEST_FILE("status.404.reply"), + TEST_FILE("testdocument.html"))); + + QmlComponent component(&engine, TEST_FILE("statusText.qml")); + QObject *object = component.beginCreate(engine.rootContext()); + QVERIFY(object != 0); + object->setProperty("url", "http://localhost:14445/testdocument.html"); + object->setProperty("expectedStatus", "Document not found"); + component.completeCreate(); + + TRY_WAIT(object->property("dataOK").toBool() == true); + + QCOMPARE(object->property("unsentException").toBool(), true); + QCOMPARE(object->property("openedException").toBool(), true); + QCOMPARE(object->property("sentException").toBool(), true); + QCOMPARE(object->property("headersReceived").toBool(), true); + QCOMPARE(object->property("loading").toBool(), true); + QCOMPARE(object->property("done").toBool(), true); + QCOMPARE(object->property("resetException").toBool(), true); + + delete object; + } +} + +void tst_xmlhttprequest::responseText() +{ + { + TestHTTPServer server(SERVER_PORT); + QVERIFY(server.isValid()); + QVERIFY(server.wait(TEST_FILE("status.expect"), + TEST_FILE("status.200.reply"), + TEST_FILE("testdocument.html"))); + + QmlComponent component(&engine, TEST_FILE("responseText.qml")); + QObject *object = component.beginCreate(engine.rootContext()); + QVERIFY(object != 0); + object->setProperty("url", "http://localhost:14445/testdocument.html"); + object->setProperty("expectedText", "QML Rocks!\n"); + component.completeCreate(); + + TRY_WAIT(object->property("dataOK").toBool() == true); + + QCOMPARE(object->property("unsent").toBool(), true); + QCOMPARE(object->property("opened").toBool(), true); + QCOMPARE(object->property("sent").toBool(), true); + QCOMPARE(object->property("headersReceived").toBool(), true); + QCOMPARE(object->property("loading").toBool(), true); + QCOMPARE(object->property("done").toBool(), true); + QCOMPARE(object->property("reset").toBool(), true); + + delete object; + } + + { + TestHTTPServer server(SERVER_PORT); + QVERIFY(server.isValid()); + QVERIFY(server.wait(TEST_FILE("status.expect"), + TEST_FILE("status.200.reply"), + QUrl())); + + QmlComponent component(&engine, TEST_FILE("responseText.qml")); + QObject *object = component.beginCreate(engine.rootContext()); + QVERIFY(object != 0); + object->setProperty("url", "http://localhost:14445/testdocument.html"); + object->setProperty("expectedText", ""); + component.completeCreate(); + + TRY_WAIT(object->property("dataOK").toBool() == true); + + QCOMPARE(object->property("unsent").toBool(), true); + QCOMPARE(object->property("opened").toBool(), true); + QCOMPARE(object->property("sent").toBool(), true); + QCOMPARE(object->property("headersReceived").toBool(), true); + QCOMPARE(object->property("loading").toBool(), true); + QCOMPARE(object->property("done").toBool(), true); + QCOMPARE(object->property("reset").toBool(), true); + + delete object; + } + + { + TestHTTPServer server(SERVER_PORT); + QVERIFY(server.isValid()); + QVERIFY(server.wait(TEST_FILE("status.expect"), + TEST_FILE("status.404.reply"), + TEST_FILE("testdocument.html"))); + + QmlComponent component(&engine, TEST_FILE("responseText.qml")); + QObject *object = component.beginCreate(engine.rootContext()); + QVERIFY(object != 0); + object->setProperty("url", "http://localhost:14445/testdocument.html"); + object->setProperty("expectedText", ""); + component.completeCreate(); + + TRY_WAIT(object->property("dataOK").toBool() == true); + + QCOMPARE(object->property("unsent").toBool(), true); + QCOMPARE(object->property("opened").toBool(), true); + QCOMPARE(object->property("sent").toBool(), true); + QCOMPARE(object->property("headersReceived").toBool(), true); + QCOMPARE(object->property("loading").toBool(), true); + QCOMPARE(object->property("done").toBool(), true); + QCOMPARE(object->property("reset").toBool(), true); + + delete object; + } +} + +void tst_xmlhttprequest::responseXML_invalid() +{ + QmlComponent component(&engine, TEST_FILE("responseXML_invalid.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + TRY_WAIT(object->property("dataOK").toBool() == true); + + QCOMPARE(object->property("xmlNull").toBool(), true); + + delete object; +} + +// Test the Document DOM element +void tst_xmlhttprequest::document() +{ + QmlComponent component(&engine, TEST_FILE("document.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + TRY_WAIT(object->property("dataOK").toBool() == true); + + QCOMPARE(object->property("xmlTest").toBool(), true); + + delete object; +} + +// Test the Element DOM element +void tst_xmlhttprequest::element() +{ + QmlComponent component(&engine, TEST_FILE("element.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + TRY_WAIT(object->property("dataOK").toBool() == true); + + QCOMPARE(object->property("xmlTest").toBool(), true); + + delete object; +} + +// Test the Attr DOM element +void tst_xmlhttprequest::attr() +{ + QmlComponent component(&engine, TEST_FILE("attr.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + TRY_WAIT(object->property("dataOK").toBool() == true); + + QCOMPARE(object->property("xmlTest").toBool(), true); + + delete object; } QTEST_MAIN(tst_xmlhttprequest) |