Adding cross-browser XMLHttpRequest functionality and convenience methods around it in the OpenLayers.Request namespace. Deprecating OpenLayers.Ajax.Request. Full support sync/async requests using all HTTP verbs now. r=elemoine (closes #1565)

git-svn-id: http://svn.openlayers.org/trunk/openlayers@7335 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
Tim Schaub
2008-06-09 19:51:38 +00:00
parent c3ca41b3be
commit 3c70e78e47
18 changed files with 924 additions and 120 deletions
+15 -7
View File
@@ -4,13 +4,21 @@
<script type="text/javascript">
function test_Ajax_loadUrl(t) {
t.plan(1);
var req = OpenLayers.Ajax.Request;
OpenLayers.ProxyHost = "/?url=";
OpenLayers.Ajax.Request.prototype.request = function(uri) {
t.eq(uri, "/?url=http%3A%2F%2Fexample.com%2F%3Fformat%3Dimage%2Bkml", "URI matches what we expect from loadurl");
}
OpenLayers.loadURL("http://example.com/?format=image+kml");
t.plan(5);
var _get = OpenLayers.Request.GET;
var caller = {};
var onComplete = function() {};
var onFailure = function() {};
var params = {};
OpenLayers.Request.GET = function(config) {
t.eq(config.url, "http://example.com/?format=image+kml", "correct url")
t.eq(config.params, params, "correct params");
t.eq(config.scope, caller, "correct scope");
t.ok(config.success === onComplete, "correct success callback");
t.ok(config.failure === onFailure, "correct failure callback");
};
OpenLayers.loadURL("http://example.com/?format=image+kml", params, caller, onComplete, onFailure);
OpenLayers.Request.GET = _get;
}
</script>
</head>
+205
View File
@@ -0,0 +1,205 @@
<html>
<head>
<script src="../lib/OpenLayers.js"></script>
<script type="text/javascript">
function setup() {
window._xhr = OpenLayers.Request.XMLHttpRequest;
var anon = new Function();
OpenLayers.Request.XMLHttpRequest = function() {};
OpenLayers.Request.XMLHttpRequest.prototype = {
open: anon,
setRequestHeader: anon,
send: anon
};
OpenLayers.Request.XMLHttpRequest.DONE = 4;
}
function teardown() {
OpenLayers.Request.XMLHttpRequest = window._xhr;
delete window._xhr;
}
function test_issue(t) {
setup();
t.plan(18);
var request, config;
var proto = OpenLayers.Request.XMLHttpRequest.prototype;
var issue = OpenLayers.Function.bind(OpenLayers.Request.issue,
OpenLayers.Request);
// test that issue returns a new XMLHttpRequest - 1 test
request = issue();
t.ok(request instanceof OpenLayers.Request.XMLHttpRequest,
"returns an XMLHttpRequest instance");
// test that issue calls xhr.open with correct args from config - 5 tests
var _open = proto.open;
config = {
method: "foo",
url: "http://nowhere",
async: "bar",
user: "uncle",
password: "sam"
};
proto.open = function(method, url, async, user, password) {
t.eq(method, config.method, "open called with correct method");
t.eq(url, config.url, "open called with correct url");
t.eq(async, config.async, "open called with correct async");
t.eq(user, config.user, "open called with correct user");
t.eq(password, config.password, "open called with correct password");
}
request = issue(config);
proto.open = _open;
// test that headers are correctly set - 4 tests
var _setRequestHeader = proto.setRequestHeader;
config = {
headers: {
foo: "bar",
chicken: "soup"
}
};
proto.setRequestHeader = function(key, value) {
t.ok(key in config.headers, "setRequestHeader called with key: " + key);
t.eq(value, config.headers[key], "setRequestHeader called with correct value: " + value);
}
request = issue(config);
proto.setRequestHeader = _setRequestHeader;
// test that callback is called (no scope) - 1 test
var unbound = function(request) {
t.ok(request instanceof OpenLayers.Request.XMLHttpRequest,
"unbound callback called with xhr instance");
}
config = {
callback: unbound
};
request = issue(config);
request.readyState = OpenLayers.Request.XMLHttpRequest.DONE;
request.onreadystatechange();
// test that callback is called (with scope) - 2 tests
var obj = {};
var bound = function(request) {
t.ok(this === obj, "bound callback has correct scope");
t.ok(request instanceof OpenLayers.Request.XMLHttpRequest,
"bound callback called with xhr instance");
}
config = {
callback: bound,
scope: obj
};
request = issue(config);
request.readyState = 4;
request.onreadystatechange();
// test that send is called with data - 1 test
var _send = proto.send;
config = {
method: "PUT",
data: "bling"
};
proto.send = function(data) {
t.eq(data, config.data, "send called with correct data");
}
request = issue(config);
proto.send = _send;
// test that optional success callback is only called with 200s and
// failure is only called with non-200s
var _send = proto.send;
proto.send = function() {};
config = {
success: function(req) {
t.ok(req.status >= 200 && req.status < 300,
"success callback called with " + req.status + " status");
},
failure: function(req) {
t.ok(req.status < 200 || req.status >= 300,
"failure callback called with " + req.status + " status");
}
};
request = issue(config);
request.readyState = 4;
// mock up status 200 (1 test)
request.status = 200;
request.onreadystatechange();
// mock up status 299 (1 test)
request.status = 299;
request.onreadystatechange();
// mock up status 100 (1 test)
request.status = 100;
request.onreadystatechange();
// mock up status 300 (1 test)
request.status = 300;
request.onreadystatechange();
proto.send = _send;
teardown();
}
function test_GET(t) {
t.plan(1);
var _issue = OpenLayers.Request.issue;
OpenLayers.Request.issue = function(config) {
t.eq(config.method, "GET", "calls issue with correct method");
}
OpenLayers.Request.GET();
OpenLayers.Request.issue = _issue;
}
function test_POST(t) {
t.plan(1);
var _issue = OpenLayers.Request.issue;
OpenLayers.Request.issue = function(config) {
t.eq(config.method, "POST", "calls issue with correct method");
}
OpenLayers.Request.POST();
OpenLayers.Request.issue = _issue;
}
function test_PUT(t) {
t.plan(1);
var _issue = OpenLayers.Request.issue;
OpenLayers.Request.issue = function(config) {
t.eq(config.method, "PUT", "calls issue with correct method");
}
OpenLayers.Request.PUT();
OpenLayers.Request.issue = _issue;
}
function test_DELETE(t) {
t.plan(1);
var _issue = OpenLayers.Request.issue;
OpenLayers.Request.issue = function(config) {
t.eq(config.method, "DELETE", "calls issue with correct method");
}
OpenLayers.Request.DELETE();
OpenLayers.Request.issue = _issue;
}
function test_HEAD(t) {
t.plan(1);
var _issue = OpenLayers.Request.issue;
OpenLayers.Request.issue = function(config) {
t.eq(config.method, "HEAD", "calls issue with correct method");
}
OpenLayers.Request.HEAD();
OpenLayers.Request.issue = _issue;
}
function test_OPTIONS(t) {
t.plan(1);
var _issue = OpenLayers.Request.issue;
OpenLayers.Request.issue = function(config) {
t.eq(config.method, "OPTIONS", "calls issue with correct method");
}
OpenLayers.Request.OPTIONS();
OpenLayers.Request.issue = _issue;
}
</script>
</head>
<body>
</body>
</html>
+14
View File
@@ -0,0 +1,14 @@
<html>
<head>
<script src="../../lib/OpenLayers.js"></script>
<script type="text/javascript">
function test_constructor(t) {
t.plan(1);
t.ok(new OpenLayers.Request.XMLHttpRequest(),
"constructor didn't fail and we trust the code is well tested in OpenLayers.Request methods");
}
</script>
</head>
<body>
</body>
</html>
+8 -8
View File
@@ -64,12 +64,12 @@
var g_Success = {};
var tLoadURL = OpenLayers.loadURL;
OpenLayers.loadURL = function(url, params, caller, onComplete) {
t.ok(url == tile.url, "tile's url correctly passed as 1st param to loadURL");
t.ok(params == null, "null passed as 2nd param to loadURL");
t.ok(caller == tile, "tile passed as 3rd param to loadURL");
t.ok(onComplete == g_Success, "success param from loadFeaturesForRegion() passed as 4th param to loadURL");
var _get = OpenLayers.Request.GET;
OpenLayers.Request.GET = function(config) {
t.ok(config.url == tile.url, "tile's url correctly passed");
t.ok(config.params == null, "null params");
t.ok(config.scope == tile, "tile passed as scope");
t.ok(config.success == g_Success, "success passed");
};
//no running request -- 4 tests
@@ -82,8 +82,8 @@
}
};
OpenLayers.Tile.WFS.prototype.loadFeaturesForRegion.apply(tile, [g_Success]);
OpenLayers.loadURL = tLoadURL;
OpenLayers.Request.GET = _get;
}
function test_Tile_WFS_destroy(t) {
+2
View File
@@ -57,6 +57,8 @@
<li>Lang.html</li>
<li>Layer.html</li>
<li>Renderer.html</li>
<li>Request.html</li>
<li>Request/XMLHttpRequest.html</li>
<li>Layer/EventPane.html</li>
<li>Layer/FixedZoomLevels.html</li>
<li>Layer/GeoRSS.html</li>
+22 -43
View File
@@ -1,70 +1,49 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Ajax Acceptance Test</title>
<style type="text/css">
body {
font-size: 0.8em;
}
p {
padding-top: 1em;
}
.buttons {
margin: 1em;
float: left;
}
</style>
<title>XHR Acceptance Test</title>
<script src="../../lib/OpenLayers.js"></script>
<script type="text/javascript">
var url = "ajax.txt";
function sendSynchronous(){
var request = new OpenLayers.Ajax.Request(url, {
'asynchronous': false,
onComplete: function() {
var request = OpenLayers.Request.GET({
url: url,
async: false,
callback: function() {
document.getElementById('send_sync').value += 'request completed\n';
}
});
document.getElementById('send_sync').value += 'other processing\n';
}
function sendAsynchronous(){
var request = new OpenLayers.Ajax.Request(url, {
onComplete: function() {
var request = OpenLayers.Request.GET({
url: url,
callback: function() {
document.getElementById('send_sync').value += 'request completed\n';
}
});
document.getElementById('send_sync').value += 'other processing\n';
}
function sendAndAbort(){
var request = new OpenLayers.Ajax.Request(url, {
onComplete: function(request) {
if (request.responseText == '') {
document.getElementById('send_sync').value += 'request aborted\n';
}
var request = OpenLayers.Request.GET({
url: url,
callback: function() {
document.getElementById('send_sync').value += 'never called\n';
}
});
request.transport.abort();
request.abort();
document.getElementById('send_sync').value += 'other processing\n';
}
</script>
</head>
<body >
<div class="buttons">
<button onclick="sendSynchronous()">Send an synchronous Ajax request</button><br />
<button onclick="sendAsynchronous()">Send an asynchronous Ajax request</button><br />
<button onclick="sendAndAbort()">Send a request and abort it</button><br />
</script>
</head>
<body >
<button onclick="sendSynchronous()">synchronous</button>
expected output: "request completed" then "other processing"<br />
<button onclick="sendAsynchronous()">asynchronous</button>
expected output: "other processing" then "request completed"<br />
<button onclick="sendAndAbort()">send and abort</button>
expected output: "other processing" (and not "never called")<br />
<textarea id="send_sync" rows="6"></textarea><br />
<button onclick="document.getElementById('send_sync').value = ''">Clear</button>
</div>
<p><b></b></p>
<p>Clicking on the different buttons should give the following results in the textarea below :</p>
<ul>
<li>synchronous: "request completed" then "other processing"</li>
<li>asynchronous: "other processing" then "request completed"</li>
<li>abort: "request aborted" then "other processing" (note that real XHR behavior would not call onComplete with abort - meaning "request aborted" would not be displayed here)</li>
</ul>
</body>
</html>