accessibility-developer-tools
Version:
This is a library of accessibility-related testing and utility code.
916 lines (704 loc) • 26.1 kB
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');
goog.require('goog.userAgent.product');
function MockXmlHttp() {
/**
* The request headers for this XmlHttpRequest.
* @type {!Object<string>}
*/
this.requestHeaders = {};
/**
* The response headers for this XmlHttpRequest.
* @type {!Object<string>}
*/
this.responseHeaders = {};
/**
* The upload object associated with this XmlHttpRequest.
* @type {!Object}
*/
this.upload = {};
}
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.requestHeaders[key] = value;
};
/**
* @param {string} key
* @return {?string}
*/
MockXmlHttp.prototype.getResponseHeader = function(key) {
return key in this.responseHeaders ? this.responseHeaders[key] : null;
};
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() {
if (goog.userAgent.product.SAFARI) {
// TODO(b/20733468): Disabled so we can get the rest of the Closure test
// suite running in a continuous build. Will investigate later.
return;
}
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 successful', 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() {
if (goog.userAgent.product.SAFARI) {
// TODO(b/20733468): Disabled so we can get the rest of the Closure test
// suite running in a continuous build. Will investigate later.
return;
}
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 successful', 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() {
if (goog.userAgent.product.SAFARI) {
// TODO(b/20733468): Disabled so we can get the rest of the Closure test
// suite running in a continuous build. Will investigate later.
return;
}
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() {
if (goog.userAgent.product.SAFARI) {
// TODO(b/20733468): Disabled so we can get the rest of the Closure test
// suite running in a continuous build. Will investigate later.
return;
}
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() {
if (goog.userAgent.product.SAFARI) {
// TODO(b/20733468): Disabled so we can get the rest of the Closure test
// suite running in a continuous build. Will investigate later.
return;
}
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 successful', 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 successful', 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 successful', 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 successful', 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 successful', 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() {
if (goog.userAgent.product.SAFARI) {
// TODO(b/20733468): Disabled so we can get the rest of the Closure test
// suite running in a continuous build. Will investigate later.
return;
}
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 successful', 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 successful', 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 successful', 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 successful', 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 successful', 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() {
if (goog.userAgent.product.SAFARI) {
// TODO(b/20733468): Disabled so we can get the rest of the Closure test
// suite running in a continuous build. Will investigate later.
return;
}
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.requestHeaders;
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.requestHeaders;
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.requestHeaders);
}
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.requestHeaders;
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.requestHeaders;
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 + ': goog.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 testSetProgressEventsEnabled() {
// The default MockXhr object contained by the XhrIo object has no
// reference to the necessary onprogress field. This is equivalent
// to a browser which does not support progress events.
var progressNotSupported = new goog.net.XhrIo;
progressNotSupported.setProgressEventsEnabled(true);
assertTrue(progressNotSupported.getProgressEventsEnabled());
progressNotSupported.send('url');
assertUndefined(
'Progress is not supported for downloads on this request.',
progressNotSupported.xhr_.onprogress);
assertUndefined(
'Progress is not supported for uploads on this request.',
progressNotSupported.xhr_.upload.onprogress);
// The following tests will include the necessary onprogress fields
// indicating progress events are supported.
MockXmlHttp.prototype.onprogress = null;
var progressDisabled = new goog.net.XhrIo;
progressDisabled.setProgressEventsEnabled(false);
assertFalse(progressDisabled.getProgressEventsEnabled());
progressDisabled.send('url');
assertNull(
'No progress handler should be set for downloads.',
progressDisabled.xhr_.onprogress);
assertUndefined(
'No progress handler should be set for uploads.',
progressDisabled.xhr_.upload.onprogress);
var progressEnabled = new goog.net.XhrIo;
progressEnabled.setProgressEventsEnabled(true);
assertTrue(progressEnabled.getProgressEventsEnabled());
progressEnabled.send('url');
assertTrue(
'Progress handler should be set for downloads.',
goog.isFunction(progressEnabled.xhr_.onprogress));
assertTrue(
'Progress handler should be set for uploads.',
goog.isFunction(progressEnabled.xhr_.upload.onprogress));
// Clean-up.
delete MockXmlHttp.prototype.onprogress;
}
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 testGetResponseHeader() {
var x = new goog.net.XhrIo();
x.send('http://foo');
x.xhr_.responseHeaders['foo'] = null;
x.xhr_.responseHeaders['bar'] = 'xyz';
x.xhr_.responseHeaders['baz'] = '';
// All headers should be undefined prior to the request completing.
assertUndefined(x.getResponseHeader('foo'));
assertUndefined(x.getResponseHeader('bar'));
assertUndefined(x.getResponseHeader('baz'));
x.xhr_.readyState = goog.net.XmlHttp.ReadyState.COMPLETE;
assertUndefined(x.getResponseHeader('foo'));
assertEquals('xyz', x.getResponseHeader('bar'));
assertEquals('', x.getResponseHeader('baz'));
}
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']);
}