795 lines
21 KiB
JavaScript
795 lines
21 KiB
JavaScript
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS-IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
goog.provide('goog.net.XhrIoTest');
|
|
goog.setTestOnly('goog.net.XhrIoTest');
|
|
|
|
goog.require('goog.Uri');
|
|
goog.require('goog.debug.EntryPointMonitor');
|
|
goog.require('goog.debug.ErrorHandler');
|
|
goog.require('goog.debug.entryPointRegistry');
|
|
goog.require('goog.events');
|
|
goog.require('goog.functions');
|
|
goog.require('goog.net.EventType');
|
|
goog.require('goog.net.WrapperXmlHttpFactory');
|
|
goog.require('goog.net.XhrIo');
|
|
goog.require('goog.net.XmlHttp');
|
|
goog.require('goog.object');
|
|
goog.require('goog.string');
|
|
goog.require('goog.testing.MockClock');
|
|
goog.require('goog.testing.PropertyReplacer');
|
|
goog.require('goog.testing.jsunit');
|
|
goog.require('goog.testing.net.XhrIo');
|
|
goog.require('goog.testing.recordFunction');
|
|
|
|
function MockXmlHttp() {
|
|
/**
|
|
* The headers for this XmlHttpRequest.
|
|
* @type {!Object<string>}
|
|
*/
|
|
this.headers = {};
|
|
}
|
|
|
|
MockXmlHttp.prototype.readyState = goog.net.XmlHttp.ReadyState.UNINITIALIZED;
|
|
|
|
MockXmlHttp.prototype.status = 200;
|
|
|
|
MockXmlHttp.syncSend = false;
|
|
|
|
MockXmlHttp.prototype.send = function(opt_data) {
|
|
this.readyState = goog.net.XmlHttp.ReadyState.UNINITIALIZED;
|
|
|
|
if (MockXmlHttp.syncSend) {
|
|
this.complete();
|
|
}
|
|
|
|
};
|
|
|
|
MockXmlHttp.prototype.complete = function() {
|
|
this.readyState = goog.net.XmlHttp.ReadyState.LOADING;
|
|
this.onreadystatechange();
|
|
|
|
this.readyState = goog.net.XmlHttp.ReadyState.LOADED;
|
|
this.onreadystatechange();
|
|
|
|
this.readyState = goog.net.XmlHttp.ReadyState.INTERACTIVE;
|
|
this.onreadystatechange();
|
|
|
|
this.readyState = goog.net.XmlHttp.ReadyState.COMPLETE;
|
|
this.onreadystatechange();
|
|
};
|
|
|
|
|
|
MockXmlHttp.prototype.open = function(verb, uri, async) {
|
|
};
|
|
|
|
MockXmlHttp.prototype.abort = function() {};
|
|
|
|
MockXmlHttp.prototype.setRequestHeader = function(key, value) {
|
|
this.headers[key] = value;
|
|
};
|
|
|
|
var lastMockXmlHttp;
|
|
goog.net.XmlHttp.setGlobalFactory(new goog.net.WrapperXmlHttpFactory(
|
|
function() {
|
|
lastMockXmlHttp = new MockXmlHttp();
|
|
return lastMockXmlHttp;
|
|
},
|
|
function() {
|
|
return {};
|
|
}));
|
|
|
|
|
|
var propertyReplacer = new goog.testing.PropertyReplacer();
|
|
var clock;
|
|
var originalEntryPoint =
|
|
goog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_;
|
|
|
|
function setUp() {
|
|
lastMockXmlHttp = null;
|
|
clock = new goog.testing.MockClock(true);
|
|
}
|
|
|
|
function tearDown() {
|
|
propertyReplacer.reset();
|
|
clock.dispose();
|
|
goog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_ = originalEntryPoint;
|
|
}
|
|
|
|
|
|
function testSyncSend() {
|
|
MockXmlHttp.syncSend = true;
|
|
var count = 0;
|
|
|
|
var x = new goog.net.XhrIo;
|
|
goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
|
|
assertFalse('Should not fire complete from inside send', inSend);
|
|
assertTrue('Should be succesful', e.target.isSuccess());
|
|
count++;
|
|
|
|
});
|
|
|
|
var inSend = true;
|
|
x.send('url');
|
|
inSend = false;
|
|
|
|
clock.tick(1); // callOnce(f, 0, ...)
|
|
|
|
assertEquals('Complete should have been called once', 1, count);
|
|
}
|
|
|
|
function testSyncSendFailure() {
|
|
MockXmlHttp.syncSend = true;
|
|
var count = 0;
|
|
|
|
var x = new goog.net.XhrIo;
|
|
goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
|
|
assertFalse('Should not fire complete from inside send', inSend);
|
|
assertFalse('Should not be succesful', e.target.isSuccess());
|
|
count++;
|
|
});
|
|
|
|
var inSend = true;
|
|
x.send('url');
|
|
lastMockXmlHttp.status = 404;
|
|
inSend = false;
|
|
|
|
clock.tick(1); // callOnce(f, 0, ...)
|
|
|
|
assertEquals('Complete should have been called once', 1, count);
|
|
}
|
|
|
|
|
|
function testSendRelativeZeroStatus() {
|
|
MockXmlHttp.syncSend = true;
|
|
var count = 0;
|
|
|
|
var x = new goog.net.XhrIo;
|
|
goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
|
|
assertFalse('Should not fire complete from inside send', inSend);
|
|
assertEquals('Should be the same as ', e.target.isSuccess(),
|
|
window.location.href.toLowerCase().indexOf('file:') == 0);
|
|
count++;
|
|
});
|
|
|
|
var inSend = true;
|
|
x.send('relative');
|
|
lastMockXmlHttp.status = 0;
|
|
inSend = false;
|
|
|
|
clock.tick(1); // callOnce(f, 0, ...)
|
|
|
|
assertEquals('Complete should have been called once', 1, count);
|
|
}
|
|
|
|
|
|
function testSendRelativeUriZeroStatus() {
|
|
MockXmlHttp.syncSend = true;
|
|
var count = 0;
|
|
|
|
var x = new goog.net.XhrIo;
|
|
goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
|
|
assertFalse('Should not fire complete from inside send', inSend);
|
|
assertEquals('Should be the same as ', e.target.isSuccess(),
|
|
window.location.href.toLowerCase().indexOf('file:') == 0);
|
|
count++;
|
|
});
|
|
|
|
var inSend = true;
|
|
x.send(goog.Uri.parse('relative'));
|
|
lastMockXmlHttp.status = 0;
|
|
inSend = false;
|
|
|
|
clock.tick(1); // callOnce(f, 0, ...)
|
|
|
|
assertEquals('Complete should have been called once', 1, count);
|
|
}
|
|
|
|
|
|
function testSendHttpZeroStatusFailure() {
|
|
MockXmlHttp.syncSend = true;
|
|
var count = 0;
|
|
|
|
var x = new goog.net.XhrIo;
|
|
goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
|
|
assertFalse('Should not fire complete from inside send', inSend);
|
|
assertFalse('Should not be succesful', e.target.isSuccess());
|
|
count++;
|
|
});
|
|
|
|
var inSend = true;
|
|
x.send('http://foo');
|
|
lastMockXmlHttp.status = 0;
|
|
inSend = false;
|
|
|
|
clock.tick(1); // callOnce(f, 0, ...)
|
|
|
|
assertEquals('Complete should have been called once', 1, count);
|
|
}
|
|
|
|
|
|
function testSendHttpUpperZeroStatusFailure() {
|
|
MockXmlHttp.syncSend = true;
|
|
var count = 0;
|
|
|
|
var x = new goog.net.XhrIo;
|
|
goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
|
|
assertFalse('Should not fire complete from inside send', inSend);
|
|
assertFalse('Should not be succesful', e.target.isSuccess());
|
|
count++;
|
|
});
|
|
|
|
var inSend = true;
|
|
x.send('HTTP://foo');
|
|
lastMockXmlHttp.status = 0;
|
|
inSend = false;
|
|
|
|
clock.tick(1); // callOnce(f, 0, ...)
|
|
|
|
assertEquals('Complete should have been called once', 1, count);
|
|
}
|
|
|
|
|
|
function testSendHttpUpperUriZeroStatusFailure() {
|
|
MockXmlHttp.syncSend = true;
|
|
var count = 0;
|
|
|
|
var x = new goog.net.XhrIo;
|
|
goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
|
|
assertFalse('Should not fire complete from inside send', inSend);
|
|
assertFalse('Should not be succesful', e.target.isSuccess());
|
|
count++;
|
|
});
|
|
|
|
var inSend = true;
|
|
x.send(goog.Uri.parse('HTTP://foo'));
|
|
lastMockXmlHttp.status = 0;
|
|
inSend = false;
|
|
|
|
clock.tick(1); // callOnce(f, 0, ...)
|
|
|
|
assertEquals('Complete should have been called once', 1, count);
|
|
}
|
|
|
|
|
|
function testSendHttpUriZeroStatusFailure() {
|
|
MockXmlHttp.syncSend = true;
|
|
var count = 0;
|
|
|
|
var x = new goog.net.XhrIo;
|
|
goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
|
|
assertFalse('Should not fire complete from inside send', inSend);
|
|
assertFalse('Should not be succesful', e.target.isSuccess());
|
|
count++;
|
|
});
|
|
|
|
var inSend = true;
|
|
x.send(goog.Uri.parse('http://foo'));
|
|
lastMockXmlHttp.status = 0;
|
|
inSend = false;
|
|
|
|
clock.tick(1); // callOnce(f, 0, ...)
|
|
|
|
assertEquals('Complete should have been called once', 1, count);
|
|
}
|
|
|
|
|
|
function testSendHttpUriZeroStatusFailure() {
|
|
MockXmlHttp.syncSend = true;
|
|
var count = 0;
|
|
|
|
var x = new goog.net.XhrIo;
|
|
goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
|
|
assertFalse('Should not fire complete from inside send', inSend);
|
|
assertFalse('Should not be succesful', e.target.isSuccess());
|
|
count++;
|
|
});
|
|
|
|
var inSend = true;
|
|
x.send(goog.Uri.parse('HTTP://foo'));
|
|
lastMockXmlHttp.status = 0;
|
|
inSend = false;
|
|
|
|
clock.tick(1); // callOnce(f, 0, ...)
|
|
|
|
assertEquals('Complete should have been called once', 1, count);
|
|
}
|
|
|
|
|
|
function testSendHttpsZeroStatusFailure() {
|
|
MockXmlHttp.syncSend = true;
|
|
var count = 0;
|
|
|
|
var x = new goog.net.XhrIo;
|
|
goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
|
|
assertFalse('Should not fire complete from inside send', inSend);
|
|
assertFalse('Should not be succesful', e.target.isSuccess());
|
|
count++;
|
|
});
|
|
|
|
var inSend = true;
|
|
x.send('https://foo');
|
|
lastMockXmlHttp.status = 0;
|
|
inSend = false;
|
|
|
|
clock.tick(1); // callOnce(f, 0, ...)
|
|
|
|
assertEquals('Complete should have been called once', 1, count);
|
|
}
|
|
|
|
|
|
function testSendFileUpperZeroStatusSuccess() {
|
|
MockXmlHttp.syncSend = true;
|
|
var count = 0;
|
|
|
|
var x = new goog.net.XhrIo;
|
|
goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
|
|
assertFalse('Should not fire complete from inside send', inSend);
|
|
assertTrue('Should not be succesful', e.target.isSuccess());
|
|
count++;
|
|
});
|
|
|
|
var inSend = true;
|
|
x.send('FILE:///foo');
|
|
lastMockXmlHttp.status = 0;
|
|
inSend = false;
|
|
|
|
clock.tick(1); // callOnce(f, 0, ...)
|
|
|
|
assertEquals('Complete should have been called once', 1, count);
|
|
}
|
|
|
|
|
|
function testSendFileUriZeroStatusSuccess() {
|
|
MockXmlHttp.syncSend = true;
|
|
var count = 0;
|
|
|
|
var x = new goog.net.XhrIo;
|
|
goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
|
|
assertFalse('Should not fire complete from inside send', inSend);
|
|
assertTrue('Should not be succesful', e.target.isSuccess());
|
|
count++;
|
|
});
|
|
|
|
var inSend = true;
|
|
x.send(goog.Uri.parse('file:///foo'));
|
|
lastMockXmlHttp.status = 0;
|
|
inSend = false;
|
|
|
|
clock.tick(1); // callOnce(f, 0, ...)
|
|
|
|
assertEquals('Complete should have been called once', 1, count);
|
|
}
|
|
|
|
|
|
function testSendDummyUriZeroStatusSuccess() {
|
|
MockXmlHttp.syncSend = true;
|
|
var count = 0;
|
|
|
|
var x = new goog.net.XhrIo;
|
|
goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
|
|
assertFalse('Should not fire complete from inside send', inSend);
|
|
assertTrue('Should not be succesful', e.target.isSuccess());
|
|
count++;
|
|
});
|
|
|
|
var inSend = true;
|
|
x.send(goog.Uri.parse('dummy:///foo'));
|
|
lastMockXmlHttp.status = 0;
|
|
inSend = false;
|
|
|
|
clock.tick(1); // callOnce(f, 0, ...)
|
|
|
|
assertEquals('Complete should have been called once', 1, count);
|
|
}
|
|
|
|
|
|
function testSendFileUpperUriZeroStatusSuccess() {
|
|
MockXmlHttp.syncSend = true;
|
|
var count = 0;
|
|
|
|
var x = new goog.net.XhrIo;
|
|
goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
|
|
assertFalse('Should not fire complete from inside send', inSend);
|
|
assertTrue('Should not be succesful', e.target.isSuccess());
|
|
count++;
|
|
});
|
|
|
|
var inSend = true;
|
|
x.send(goog.Uri.parse('FILE:///foo'));
|
|
lastMockXmlHttp.status = 0;
|
|
inSend = false;
|
|
|
|
clock.tick(1); // callOnce(f, 0, ...)
|
|
|
|
assertEquals('Complete should have been called once', 1, count);
|
|
}
|
|
|
|
|
|
function testSendFromListener() {
|
|
MockXmlHttp.syncSend = true;
|
|
var count = 0;
|
|
|
|
var x = new goog.net.XhrIo;
|
|
goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
|
|
count++;
|
|
|
|
var e = assertThrows(function() {
|
|
x.send('url2');
|
|
});
|
|
assertEquals('[goog.net.XhrIo] Object is active with another request=url' +
|
|
'; newUri=url2', e.message);
|
|
});
|
|
|
|
x.send('url');
|
|
|
|
clock.tick(1); // callOnce(f, 0, ...)
|
|
|
|
assertEquals('Complete should have been called once', 1, count);
|
|
}
|
|
|
|
|
|
function testStatesDuringEvents() {
|
|
MockXmlHttp.syncSend = true;
|
|
|
|
var x = new goog.net.XhrIo;
|
|
var readyState = goog.net.XmlHttp.ReadyState.UNINITIALIZED;
|
|
goog.events.listen(x, goog.net.EventType.READY_STATE_CHANGE, function(e) {
|
|
readyState++;
|
|
assertObjectEquals(e.target, x);
|
|
assertEquals(x.getReadyState(), readyState);
|
|
assertTrue(x.isActive());
|
|
});
|
|
goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
|
|
assertObjectEquals(e.target, x);
|
|
assertTrue(x.isActive());
|
|
});
|
|
goog.events.listen(x, goog.net.EventType.SUCCESS, function(e) {
|
|
assertObjectEquals(e.target, x);
|
|
assertTrue(x.isActive());
|
|
});
|
|
goog.events.listen(x, goog.net.EventType.READY, function(e) {
|
|
assertObjectEquals(e.target, x);
|
|
assertFalse(x.isActive());
|
|
});
|
|
|
|
x.send('url');
|
|
|
|
clock.tick(1); // callOnce(f, 0, ...)
|
|
}
|
|
|
|
|
|
function testProtectEntryPointCalledOnAsyncSend() {
|
|
MockXmlHttp.syncSend = false;
|
|
|
|
var errorHandlerCallbackCalled = false;
|
|
var errorHandler = new goog.debug.ErrorHandler(function() {
|
|
errorHandlerCallbackCalled = true;
|
|
});
|
|
|
|
goog.net.XhrIo.protectEntryPoints(errorHandler);
|
|
|
|
var x = new goog.net.XhrIo;
|
|
goog.events.listen(x, goog.net.EventType.READY_STATE_CHANGE, function(e) {
|
|
throw Error();
|
|
});
|
|
|
|
x.send('url');
|
|
assertThrows(function() {
|
|
lastMockXmlHttp.complete();
|
|
});
|
|
|
|
assertTrue('Error handler callback should be called on async send.',
|
|
errorHandlerCallbackCalled);
|
|
}
|
|
|
|
function testXHRIsDiposedEvenIfAListenerThrowsAnExceptionOnComplete() {
|
|
MockXmlHttp.syncSend = false;
|
|
|
|
var x = new goog.net.XhrIo;
|
|
|
|
goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
|
|
throw Error();
|
|
}, false, x);
|
|
|
|
x.send('url');
|
|
assertThrows(function() {
|
|
lastMockXmlHttp.complete();
|
|
});
|
|
|
|
// The XHR should have been disposed, even though the listener threw an
|
|
// exception.
|
|
assertNull(x.xhr_);
|
|
}
|
|
|
|
function testDisposeInternalDoesNotAbortXhrRequestObjectWhenActiveIsFalse() {
|
|
MockXmlHttp.syncSend = false;
|
|
|
|
var xmlHttp = goog.net.XmlHttp;
|
|
var abortCalled = false;
|
|
var x = new goog.net.XhrIo;
|
|
|
|
goog.net.XmlHttp.prototype.abort = function() { abortCalled = true; };
|
|
|
|
goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
|
|
this.active_ = false;
|
|
this.dispose();
|
|
}, false, x);
|
|
|
|
x.send('url');
|
|
lastMockXmlHttp.complete();
|
|
|
|
goog.net.XmlHttp = xmlHttp;
|
|
assertFalse(abortCalled);
|
|
}
|
|
|
|
function testCallingAbortFromWithinAbortCallbackDoesntLoop() {
|
|
var x = new goog.net.XhrIo;
|
|
goog.events.listen(x, goog.net.EventType.ABORT, function(e) {
|
|
x.abort(); // Shouldn't get a stack overflow
|
|
});
|
|
x.send('url');
|
|
x.abort();
|
|
}
|
|
|
|
function testPostSetsContentTypeHeader() {
|
|
var x = new goog.net.XhrIo;
|
|
|
|
x.send('url', 'POST', 'content');
|
|
var headers = lastMockXmlHttp.headers;
|
|
assertEquals(1, goog.object.getCount(headers));
|
|
assertEquals(
|
|
headers[goog.net.XhrIo.CONTENT_TYPE_HEADER],
|
|
goog.net.XhrIo.FORM_CONTENT_TYPE);
|
|
}
|
|
|
|
function testNonPostSetsContentTypeHeader() {
|
|
var x = new goog.net.XhrIo;
|
|
|
|
x.send('url', 'PUT', 'content');
|
|
headers = lastMockXmlHttp.headers;
|
|
assertEquals(1, goog.object.getCount(headers));
|
|
assertEquals(
|
|
headers[goog.net.XhrIo.CONTENT_TYPE_HEADER],
|
|
goog.net.XhrIo.FORM_CONTENT_TYPE);
|
|
}
|
|
|
|
function testContentTypeIsTreatedCaseInsensitively() {
|
|
var x = new goog.net.XhrIo;
|
|
|
|
x.send('url', 'POST', 'content', {'content-type': 'testing'});
|
|
|
|
assertObjectEquals(
|
|
'Headers should not be modified since they already contain a ' +
|
|
'content type definition',
|
|
{'content-type': 'testing'},
|
|
lastMockXmlHttp.headers);
|
|
}
|
|
|
|
function testIsContentTypeHeader_() {
|
|
assertTrue(goog.net.XhrIo.isContentTypeHeader_('content-type'));
|
|
assertTrue(goog.net.XhrIo.isContentTypeHeader_('Content-type'));
|
|
assertTrue(goog.net.XhrIo.isContentTypeHeader_('CONTENT-TYPE'));
|
|
assertTrue(goog.net.XhrIo.isContentTypeHeader_('Content-Type'));
|
|
assertFalse(goog.net.XhrIo.isContentTypeHeader_('Content Type'));
|
|
}
|
|
|
|
function testPostFormDataDoesNotSetContentTypeHeader() {
|
|
function FakeFormData() {}
|
|
|
|
propertyReplacer.set(goog.global, 'FormData', FakeFormData);
|
|
|
|
var x = new goog.net.XhrIo;
|
|
x.send('url', 'POST', new FakeFormData());
|
|
var headers = lastMockXmlHttp.headers;
|
|
assertTrue(goog.object.isEmpty(headers));
|
|
}
|
|
|
|
function testNonPostFormDataDoesNotSetContentTypeHeader() {
|
|
function FakeFormData() {}
|
|
|
|
propertyReplacer.set(goog.global, 'FormData', FakeFormData);
|
|
|
|
var x = new goog.net.XhrIo;
|
|
x.send('url', 'PUT', new FakeFormData());
|
|
headers = lastMockXmlHttp.headers;
|
|
assertTrue(goog.object.isEmpty(headers));
|
|
}
|
|
|
|
function testFactoryInjection() {
|
|
var xhr = new MockXmlHttp();
|
|
var optionsFactoryCalled = 0;
|
|
var xhrFactoryCalled = 0;
|
|
var wrapperFactory = new goog.net.WrapperXmlHttpFactory(
|
|
function() {
|
|
xhrFactoryCalled++;
|
|
return xhr;
|
|
},
|
|
function() {
|
|
optionsFactoryCalled++;
|
|
return {};
|
|
});
|
|
var xhrIo = new goog.net.XhrIo(wrapperFactory);
|
|
|
|
xhrIo.send('url');
|
|
|
|
assertEquals('XHR factory should have been called', 1, xhrFactoryCalled);
|
|
assertEquals('Options factory should have been called', 1,
|
|
optionsFactoryCalled);
|
|
}
|
|
|
|
function testGoogTestingNetXhrIoIsInSync() {
|
|
var xhrIo = new goog.net.XhrIo();
|
|
var testingXhrIo = new goog.testing.net.XhrIo();
|
|
|
|
var propertyComparator = function(value, key, obj) {
|
|
if (goog.string.endsWith(key, '_')) {
|
|
// Ignore private properties/methods
|
|
return true;
|
|
} else if (typeof value == 'function' && typeof this[key] != 'function') {
|
|
// Only type check is sufficient for functions
|
|
fail('Mismatched property:' + key + ': gooo.net.XhrIo has:<' +
|
|
value + '>; while goog.testing.net.XhrIo has:<' + this[key] + '>');
|
|
return true;
|
|
} else {
|
|
// Ignore all other type of properties.
|
|
return true;
|
|
}
|
|
};
|
|
|
|
goog.object.every(xhrIo, propertyComparator, testingXhrIo);
|
|
}
|
|
|
|
function testEntryPointRegistry() {
|
|
var monitor = new goog.debug.EntryPointMonitor();
|
|
var replacement = function() {};
|
|
monitor.wrap = goog.testing.recordFunction(
|
|
goog.functions.constant(replacement));
|
|
|
|
goog.debug.entryPointRegistry.monitorAll(monitor);
|
|
assertTrue(monitor.wrap.getCallCount() >= 1);
|
|
assertEquals(
|
|
replacement,
|
|
goog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_);
|
|
}
|
|
|
|
function testSetWithCredentials() {
|
|
// Test on XHR objects that don't have the withCredentials property (older
|
|
// browsers).
|
|
var x = new goog.net.XhrIo;
|
|
x.setWithCredentials(true);
|
|
x.send('url');
|
|
assertFalse(
|
|
'withCredentials should not be set on an XHR object if the property ' +
|
|
'does not exist.',
|
|
goog.object.containsKey(lastMockXmlHttp, 'withCredentials'));
|
|
|
|
// Test on XHR objects that have the withCredentials property.
|
|
MockXmlHttp.prototype.withCredentials = false;
|
|
x = new goog.net.XhrIo;
|
|
x.setWithCredentials(true);
|
|
x.send('url');
|
|
assertTrue(
|
|
'withCredentials should be set on an XHR object if the property exists',
|
|
goog.object.containsKey(lastMockXmlHttp, 'withCredentials'));
|
|
|
|
assertTrue(
|
|
'withCredentials value not set on XHR object',
|
|
lastMockXmlHttp.withCredentials);
|
|
|
|
// Reset the prototype so it does not effect other tests.
|
|
delete MockXmlHttp.prototype.withCredentials;
|
|
}
|
|
|
|
function testGetResponse() {
|
|
var x = new goog.net.XhrIo;
|
|
|
|
// No XHR yet
|
|
assertEquals(null, x.getResponse());
|
|
|
|
// XHR with no .response and no response type, gets text.
|
|
x.xhr_ = {};
|
|
x.xhr_.responseText = 'text';
|
|
assertEquals('text', x.getResponse());
|
|
|
|
// Response type of text gets text as well.
|
|
x.setResponseType(goog.net.XhrIo.ResponseType.TEXT);
|
|
x.xhr_.responseText = '';
|
|
assertEquals('', x.getResponse());
|
|
|
|
// Response type of array buffer gets the array buffer.
|
|
x.xhr_.mozResponseArrayBuffer = 'ab';
|
|
x.setResponseType(goog.net.XhrIo.ResponseType.ARRAY_BUFFER);
|
|
assertEquals('ab', x.getResponse());
|
|
|
|
// With a response field, it is returned no matter what value it has.
|
|
x.xhr_.response = undefined;
|
|
assertEquals(undefined, x.getResponse());
|
|
|
|
x.xhr_.response = null;
|
|
assertEquals(null, x.getResponse());
|
|
|
|
x.xhr_.response = '';
|
|
assertEquals('', x.getResponse());
|
|
|
|
x.xhr_.response = 'resp';
|
|
assertEquals('resp', x.getResponse());
|
|
}
|
|
|
|
function testGetResponseHeaders() {
|
|
var x = new goog.net.XhrIo();
|
|
|
|
// No XHR yet
|
|
assertEquals(0, goog.object.getCount(x.getResponseHeaders()));
|
|
|
|
// Simulate an XHR with 2 headers.
|
|
var headersRaw = 'test1: foo\r\ntest2: bar';
|
|
|
|
propertyReplacer.set(x, 'getAllResponseHeaders',
|
|
goog.functions.constant(headersRaw));
|
|
|
|
var headers = x.getResponseHeaders();
|
|
assertEquals(2, goog.object.getCount(headers));
|
|
assertEquals('foo', headers['test1']);
|
|
assertEquals('bar', headers['test2']);
|
|
}
|
|
|
|
function testGetResponseHeadersWithColonInValue() {
|
|
var x = new goog.net.XhrIo();
|
|
|
|
// Simulate an XHR with a colon in the http header value.
|
|
var headersRaw = 'test1: f:o:o';
|
|
|
|
propertyReplacer.set(x, 'getAllResponseHeaders',
|
|
goog.functions.constant(headersRaw));
|
|
|
|
var headers = x.getResponseHeaders();
|
|
assertEquals(1, goog.object.getCount(headers));
|
|
assertEquals('f:o:o', headers['test1']);
|
|
}
|
|
|
|
function testGetResponseHeadersMultipleValuesForOneKey() {
|
|
var x = new goog.net.XhrIo();
|
|
|
|
// No XHR yet
|
|
assertEquals(0, goog.object.getCount(x.getResponseHeaders()));
|
|
|
|
// Simulate an XHR with 2 headers.
|
|
var headersRaw = 'test1: foo\r\ntest1: bar';
|
|
|
|
propertyReplacer.set(x, 'getAllResponseHeaders',
|
|
goog.functions.constant(headersRaw));
|
|
|
|
var headers = x.getResponseHeaders();
|
|
assertEquals(1, goog.object.getCount(headers));
|
|
assertEquals('foo, bar', headers['test1']);
|
|
}
|
|
|
|
function testGetResponseHeadersEmptyHeader() {
|
|
var x = new goog.net.XhrIo();
|
|
|
|
// No XHR yet
|
|
assertEquals(0, goog.object.getCount(x.getResponseHeaders()));
|
|
|
|
// Simulate an XHR with 2 headers, the last of which is empty.
|
|
var headersRaw = 'test2: bar\r\n';
|
|
|
|
propertyReplacer.set(x, 'getAllResponseHeaders',
|
|
goog.functions.constant(headersRaw));
|
|
|
|
var headers = x.getResponseHeaders();
|
|
assertEquals(1, goog.object.getCount(headers));
|
|
assertEquals('bar', headers['test2']);
|
|
}
|