aboutsummaryrefslogtreecommitdiff
path: root/catapult/third_party/polymer/components/iron-ajax/test
diff options
context:
space:
mode:
Diffstat (limited to 'catapult/third_party/polymer/components/iron-ajax/test')
-rw-r--r--catapult/third_party/polymer/components/iron-ajax/test/index.html27
-rw-r--r--catapult/third_party/polymer/components/iron-ajax/test/iron-ajax.html968
-rw-r--r--catapult/third_party/polymer/components/iron-ajax/test/iron-request.html368
3 files changed, 1363 insertions, 0 deletions
diff --git a/catapult/third_party/polymer/components/iron-ajax/test/index.html b/catapult/third_party/polymer/components/iron-ajax/test/index.html
new file mode 100644
index 00000000..997b08f1
--- /dev/null
+++ b/catapult/third_party/polymer/components/iron-ajax/test/index.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!--
+@license
+Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+-->
+<html>
+<head>
+ <meta charset="utf-8">
+ <script src="../../webcomponentsjs/webcomponents-lite.js"></script>
+ <script src="../../web-component-tester/browser.js"></script>
+</head>
+<body>
+ <script>
+ WCT.loadSuites([
+ 'iron-request.html?wc-shadowdom=true&wc-ce=true',
+ 'iron-ajax.html?wc-shadowdom=true&wc-ce=true',
+ 'iron-request.html?dom=shadow',
+ 'iron-ajax.html?dom=shadow'
+ ]);
+ </script>
+</body>
+</html>
diff --git a/catapult/third_party/polymer/components/iron-ajax/test/iron-ajax.html b/catapult/third_party/polymer/components/iron-ajax/test/iron-ajax.html
new file mode 100644
index 00000000..eae01718
--- /dev/null
+++ b/catapult/third_party/polymer/components/iron-ajax/test/iron-ajax.html
@@ -0,0 +1,968 @@
+<!doctype html>
+<!--
+@license
+Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+-->
+<html>
+<head>
+ <title>iron-ajax</title>
+
+ <script src="../../webcomponentsjs/webcomponents-lite.js"></script>
+ <script src="../../web-component-tester/browser.js"></script>
+
+ <link rel="import" href="../../polymer/polymer.html">
+ <link rel="import" href="../../promise-polyfill/promise-polyfill.html">
+ <link rel="import" href="../iron-ajax.html">
+</head>
+<body>
+ <test-fixture id="TrivialGet">
+ <template>
+ <iron-ajax url="/responds_to_get_with_json"></iron-ajax>
+ </template>
+ </test-fixture>
+ <test-fixture id="ParamsGet">
+ <template>
+ <iron-ajax url="/responds_to_get_with_json"
+ params='{"a": "a"}'></iron-ajax>
+ </template>
+ </test-fixture>
+ <test-fixture id="AutoGet">
+ <template>
+ <iron-ajax auto url="/responds_to_get_with_json"></iron-ajax>
+ </template>
+ </test-fixture>
+ <test-fixture id="GetEcho">
+ <template>
+ <iron-ajax handle-as="json" url="/echoes_request_url"></iron-ajax>
+ </template>
+ </test-fixture>
+ <test-fixture id="TrivialPost">
+ <template>
+ <iron-ajax method="POST"
+ url="/responds_to_post_with_json"></iron-ajax>
+ </template>
+ </test-fixture>
+ <test-fixture id="DebouncedGet">
+ <template>
+ <iron-ajax auto
+ url="/responds_to_debounced_get_with_json"
+ debounce-duration="150"></iron-ajax>
+ </template>
+ </test-fixture>
+ <test-fixture id='BlankUrl'>
+ <template>
+ <iron-ajax auto handle-as='text'></iron-ajax>
+ </template>
+ </test-fixture>
+ <test-fixture id="RealPost">
+ <template>
+ <iron-ajax method="POST" url="http://httpbin.org/post"></iron-ajax>
+ </template>
+ </test-fixture>
+ <test-fixture id="Delay">
+ <template>
+ <iron-ajax url="http://httpbin.org/delay/1"></iron-ajax>
+ </template>
+ </test-fixture>
+ <test-fixture id="Bubbles">
+ <template>
+ <iron-ajax url="http://httpbin.org/post" method="POST" bubbles></iron-ajax>
+ <iron-ajax url="/responds_to_get_with_502_error_json" bubbles></iron-ajax>
+ </template>
+ </test-fixture>
+ <script>
+ 'use strict';
+ suite('<iron-ajax>', function() {
+ var responseHeaders = {
+ json: { 'Content-Type': 'application/json' },
+ plain: { 'Content-Type': 'text/plain' }
+ };
+ var ajax;
+ var request;
+ var server;
+
+ function timePasses(ms) {
+ return new Promise(function(resolve) {
+ window.setTimeout(function() {
+ resolve();
+ }, ms);
+ });
+ }
+
+ setup(function() {
+ server = sinon.fakeServer.create();
+ server.respondWith(
+ 'GET',
+ /\/responds_to_get_with_json.*/,
+ [
+ 200,
+ responseHeaders.json,
+ '{"success":true}'
+ ]
+ );
+
+ server.respondWith(
+ 'POST',
+ '/responds_to_post_with_json',
+ [
+ 200,
+ responseHeaders.json,
+ '{"post_success":true}'
+ ]
+ );
+
+ server.respondWith(
+ 'GET',
+ '/responds_to_get_with_text',
+ [
+ 200,
+ responseHeaders.plain,
+ 'Hello World'
+ ]
+ );
+
+ server.respondWith(
+ 'GET',
+ '/responds_to_debounced_get_with_json',
+ [
+ 200,
+ responseHeaders.json,
+ '{"success": "true"}'
+ ]
+ );
+
+ server.respondWith(
+ 'GET',
+ '/responds_to_get_with_502_error_json',
+ [
+ 502,
+ responseHeaders.json,
+ '{"message": "an error has occurred"}'
+ ]
+ );
+
+ ajax = fixture('TrivialGet');
+ });
+
+ teardown(function() {
+ server.restore();
+ });
+
+ // Echo requests are responded to individually and on demand, unlike the
+ // others in this file which are responded to with server.respond(),
+ // which responds to all open requests.
+ // We don't use server.respondWith here because there's no way to use it
+ // and only respond to a subset of requests.
+ // This way we can test for delayed and out of order responses and
+ // distinquish them by their responses.
+ function respondToEchoRequest(request) {
+ request.respond(200, responseHeaders.json, JSON.stringify({
+ url: request.url
+ }));
+ }
+
+ suite('when making simple GET requests for JSON', function() {
+ test('has sane defaults that love you', function() {
+ request = ajax.generateRequest();
+
+ server.respond();
+
+ expect(request.response).to.be.ok;
+ expect(request.response).to.be.an('object');
+ expect(request.response.success).to.be.equal(true);
+ });
+
+ test('will be asynchronous by default', function() {
+ expect(ajax.toRequestOptions().async).to.be.eql(true);
+ });
+ });
+
+ suite('when setting custom headers', function() {
+ test('are present in the request headers', function() {
+ ajax.headers['custom-header'] = 'valid';
+ var options = ajax.toRequestOptions();
+
+ expect(options.headers).to.be.ok;
+ expect(options.headers['custom-header']).to.be.an('string');
+ expect(options.headers.hasOwnProperty('custom-header')).to.be.equal(
+ true);
+ });
+
+ test('non-objects in headers are not applied', function() {
+ ajax.headers = 'invalid';
+ var options = ajax.toRequestOptions();
+
+ expect(Object.keys(options.headers).length).to.be.equal(0);
+ });
+ });
+
+ suite('when url isn\'t set yet', function() {
+ test('we don\'t fire any automatic requests', function() {
+ expect(server.requests.length).to.be.equal(0);
+ ajax = fixture('BlankUrl');
+
+ return timePasses(1).then(function() {
+ // We don't make any requests.
+ expect(server.requests.length).to.be.equal(0);
+
+ // Explicitly asking for the request to fire works.
+ ajax.generateRequest();
+ expect(server.requests.length).to.be.equal(1);
+ server.requests = [];
+
+ // Explicitly setting url to '' works too.
+ ajax = fixture('BlankUrl');
+ ajax.url = '';
+ return timePasses(1);
+ }).then(function() {
+ expect(server.requests.length).to.be.equal(1);
+ });
+ });
+
+ test('requestUrl remains empty despite valid queryString', function() {
+ ajax = fixture('BlankUrl');
+ expect(ajax.url).to.be.equal(undefined);
+ expect(ajax.queryString).to.be.equal('');
+ expect(ajax.requestUrl).to.be.equal('');
+
+ ajax.params = {'a':'b', 'c':'d'};
+
+ expect(ajax.queryString).to.be.equal('a=b&c=d');
+ expect(ajax.requestUrl).to.be.equal('?a=b&c=d');
+ });
+
+ test('generateRequest works with empty URL and valid queryString', function() {
+ ajax = fixture('BlankUrl');
+ expect(ajax.url).to.be.equal(undefined);
+
+ ajax.generateRequest();
+ expect(server.requests[0].url).to.be.eql('');
+
+ ajax.params = {'a':'b', 'c':'d'};
+
+ ajax.generateRequest();
+ expect(server.requests[1].url).to.be.eql('?a=b&c=d');
+ });
+ });
+
+ suite('when properties are changed', function() {
+ test('generates simple-request elements that reflect the change', function() {
+ request = ajax.generateRequest();
+
+ expect(request.xhr.method).to.be.equal('GET');
+
+ ajax.method = 'POST';
+ ajax.url = '/responds_to_post_with_json';
+
+ request = ajax.generateRequest();
+
+ expect(request.xhr.method).to.be.equal('POST');
+ });
+ });
+
+ suite('when generating a request', function() {
+ test('yields an iron-request instance', function() {
+ var IronRequest = document.createElement('iron-request').constructor;
+
+ expect(ajax.generateRequest()).to.be.instanceOf(IronRequest);
+ });
+
+ test('correctly adds params to a URL that already has some', function() {
+ ajax.url += '?a=b';
+ ajax.params = {'c': 'd'};
+
+ expect(ajax.requestUrl).to.be.equal('/responds_to_get_with_json?a=b&c=d')
+ })
+
+ test('encodes params properly', function() {
+ ajax.params = {'a b,c': 'd e f'};
+
+ expect(ajax.queryString).to.be.equal('a%20b%2Cc=d%20e%20f');
+ });
+
+ test('encodes array params properly', function() {
+ ajax.params = {'a b': ['c','d e', 'f']};
+
+ expect(ajax.queryString).to.be.equal('a%20b=c&a%20b=d%20e&a%20b=f');
+ });
+
+ test('reflects the loading state in the `loading` property', function() {
+ var request = ajax.generateRequest();
+
+ expect(ajax.loading).to.be.equal(true);
+
+ server.respond();
+
+ return request.completes.then(function() {
+ return timePasses(1);
+ }).then(function() {
+ expect(ajax.loading).to.be.equal(false);
+ });
+ });
+
+ test('the `iron-ajax-presend` event gets fired', function() {
+ var spy = sinon.spy();
+ var windowSpy = sinon.spy();
+ ajax.addEventListener('iron-ajax-presend', spy);
+ window.addEventListener('iron-ajax-presend', windowSpy);
+
+ var request = ajax.generateRequest();
+
+ server.respond()
+
+ return request.completes.then(function() {
+ expect(spy).to.be.calledOnce;
+ expect(windowSpy).not.to.be.called;
+ });
+ });
+
+ test('the loading-changed event gets fired twice', function() {
+ var count = 0;
+ ajax.addEventListener('loading-changed', function() {
+ count++;
+ });
+
+ var request = ajax.generateRequest();
+
+ server.respond();
+
+ return request.completes.then(function() {
+ return timePasses(1);
+ }).then(function() {
+ expect(count).to.be.equal(2);
+ });
+ });
+ });
+
+ suite('when there are multiple requests', function() {
+ var requests;
+ var echoAjax;
+ var promiseAllComplete;
+
+ setup(function() {
+ echoAjax = fixture('GetEcho');
+ requests = [];
+
+ for (var i = 0; i < 3; ++i) {
+ echoAjax.params = {'order': i + 1};
+ requests.push(echoAjax.generateRequest());
+ }
+ var allPromises = requests.map(function(r){return r.completes});
+ promiseAllComplete = Promise.all(allPromises);
+ });
+
+ test('holds all requests in the `activeRequests` Array', function() {
+ expect(requests).to.deep.eql(echoAjax.activeRequests);
+ });
+
+ test('empties `activeRequests` when requests are completed', function() {
+ expect(echoAjax.activeRequests.length).to.be.equal(3);
+ for (var i = 0; i < 3; i++) {
+ respondToEchoRequest(server.requests[i]);
+ }
+ return promiseAllComplete.then(function() {
+ return timePasses(1);
+ }).then(function() {
+ expect(echoAjax.activeRequests.length).to.be.equal(0);
+ });
+ });
+
+ test('avoids race conditions with last response', function() {
+ expect(echoAjax.lastResponse).to.be.equal(undefined);
+
+ // Resolving the oldest request doesn't update lastResponse.
+ respondToEchoRequest(server.requests[0]);
+ return requests[0].completes.then(function() {
+ expect(echoAjax.lastResponse).to.be.equal(undefined);
+
+ // Resolving the most recent request does!
+ respondToEchoRequest(server.requests[2]);
+ return requests[2].completes;
+ }).then(function() {
+ expect(echoAjax.lastResponse).to.be.deep.eql(
+ {url: '/echoes_request_url?order=3'});
+
+
+ // Resolving an out of order stale request after does nothing!
+ respondToEchoRequest(server.requests[1]);
+ return requests[1].completes;
+ }).then(function() {
+ expect(echoAjax.lastResponse).to.be.deep.eql(
+ {url: '/echoes_request_url?order=3'});
+ });
+ });
+
+ test('`loading` is true while the last one is loading', function() {
+ expect(echoAjax.loading).to.be.equal(true);
+
+ respondToEchoRequest(server.requests[0]);
+ return requests[0].completes.then(function() {
+ // We're still loading because requests[2] is the most recently
+ // made request.
+ expect(echoAjax.loading).to.be.equal(true);
+
+ respondToEchoRequest(server.requests[2]);
+ return requests[2].completes;
+ }).then(function() {
+ // Now we're done loading.
+ expect(echoAjax.loading).to.be.eql(false);
+
+ // Resolving an out of order stale request after should have
+ // no effect.
+ respondToEchoRequest(server.requests[1]);
+ return requests[1].completes;
+ }).then(function() {
+ expect(echoAjax.loading).to.be.eql(false);
+ });
+ });
+ });
+
+ suite('when params are changed', function() {
+ test('generates a request that reflects the change', function() {
+ ajax = fixture('ParamsGet');
+ request = ajax.generateRequest();
+
+ expect(request.xhr.url).to.be.equal('/responds_to_get_with_json?a=a');
+
+ ajax.params = {b: 'b'};
+ request = ajax.generateRequest();
+
+ expect(request.xhr.url).to.be.equal('/responds_to_get_with_json?b=b');
+ });
+ });
+
+ suite('when `auto` is enabled', function() {
+ setup(function() {
+ ajax = fixture('AutoGet');
+ });
+
+ test('automatically generates new requests', function() {
+ return new Promise(function(resolve) {
+ ajax.addEventListener('request', function() {
+ resolve();
+ });
+ });
+ });
+
+ test('does not send requests if url is not a string', function() {
+ return new Promise(function(resolve, reject) {
+ ajax.addEventListener('request', function() {
+ reject('A request was generated but url is null!');
+ });
+
+ ajax.url = null;
+ ajax.handleAs = 'text';
+
+ Polymer.Base.async(function() {
+ resolve();
+ }, 1);
+ });
+ });
+
+ test('deduplicates multiple changes to a single request', function() {
+ return new Promise(function(resolve, reject) {
+ ajax.addEventListener('request', function() {
+ server.respond();
+ });
+
+ ajax.addEventListener('response', function() {
+ try {
+ expect(ajax.activeRequests.length).to.be.eql(1);
+ resolve()
+ } catch (e) {
+ reject(e);
+ }
+ });
+
+ ajax.handleas = 'text';
+ ajax.params = { foo: 'bar' };
+ ajax.headers = { 'X-Foo': 'Bar' };
+ });
+ });
+
+ test('automatically generates new request when a sub-property of params is changed', function(done) {
+ ajax.addEventListener('request', function() {
+ server.respond();
+ });
+
+ ajax.params = { foo: 'bar' };
+ ajax.addEventListener('response', function() {
+ ajax.addEventListener('request', function() {
+ done();
+ });
+
+ ajax.set('params.foo', 'xyz');
+ });
+ });
+ });
+
+ suite('the last response', function() {
+ setup(function() {
+ request = ajax.generateRequest();
+ server.respond();
+ });
+
+ test('is accessible as a readonly property', function() {
+ return request.completes.then(function(request) {
+ expect(ajax.lastResponse).to.be.equal(request.response);
+ });
+ });
+
+
+ test('updates with each new response', function() {
+ return request.completes.then(function(request) {
+
+ expect(request.response).to.be.an('object');
+ expect(ajax.lastResponse).to.be.equal(request.response);
+
+ ajax.handleAs = 'text';
+ request = ajax.generateRequest();
+ server.respond();
+
+ return request.completes;
+ }).then(function(request) {
+ expect(request.response).to.be.a('string');
+ expect(ajax.lastResponse).to.be.equal(request.response);
+ });
+ });
+ });
+
+ suite('when making POST requests', function() {
+ setup(function() {
+ ajax = fixture('TrivialPost');
+ });
+
+ test('POSTs the value of the `body` attribute', function() {
+ var requestBody = JSON.stringify({foo: 'bar'});
+
+ ajax.body = requestBody;
+ ajax.generateRequest();
+
+ expect(server.requests[0]).to.be.ok;
+ expect(server.requests[0].requestBody).to.be.equal(requestBody);
+ });
+
+ test('if `contentType` is set to form encode, the body is encoded',function() {
+ ajax.body = {foo: 'bar\nbip', 'biz bo': 'baz blar'};
+ ajax.contentType = 'application/x-www-form-urlencoded';
+ ajax.generateRequest();
+
+ expect(server.requests[0]).to.be.ok;
+ expect(server.requests[0].requestBody).to.be.equal(
+ 'foo=bar%0D%0Abip&biz+bo=baz+blar');
+ });
+
+ test('if `contentType` is json, the body is json encoded', function() {
+ var requestObj = {foo: 'bar', baz: [1,2,3]}
+ ajax.body = requestObj;
+ ajax.contentType = 'application/json';
+ ajax.generateRequest();
+
+ expect(server.requests[0]).to.be.ok;
+ expect(server.requests[0].requestBody).to.be.equal(
+ JSON.stringify(requestObj));
+ });
+
+ suite('the examples in the documentation work', function() {
+ test('json content, body attribute is an object', function() {
+ ajax.setAttribute('body', '{"foo": "bar baz", "x": 1}');
+ ajax.contentType = 'application/json';
+ ajax.generateRequest();
+
+ expect(server.requests[0]).to.be.ok;
+ expect(server.requests[0].requestBody).to.be.equal(
+ '{"foo":"bar baz","x":1}');
+ });
+
+ test('form content, body attribute is an object', function() {
+ ajax.setAttribute('body', '{"foo": "bar baz", "x": 1}');
+ ajax.contentType = 'application/x-www-form-urlencoded';
+ ajax.generateRequest();
+
+ expect(server.requests[0]).to.be.ok;
+ expect(server.requests[0].requestBody).to.be.equal(
+ 'foo=bar+baz&x=1');
+ });
+ });
+
+ suite('and `contentType` is explicitly set to form encode', function() {
+ test('we encode a custom object', function() {
+ function Foo(bar) { this.bar = bar };
+ var requestObj = new Foo('baz');
+ ajax.body = requestObj;
+ ajax.contentType = 'application/x-www-form-urlencoded';
+ ajax.generateRequest();
+
+ expect(server.requests[0]).to.be.ok;
+ expect(server.requests[0].requestBody).to.be.equal('bar=baz');
+ });
+ })
+
+ suite('and `contentType` isn\'t set', function() {
+ test('we don\'t try to encode an ArrayBuffer', function() {
+ var requestObj = new ArrayBuffer()
+ ajax.body = requestObj;
+ ajax.generateRequest();
+
+ expect(server.requests[0]).to.be.ok;
+ // We give the browser the ArrayBuffer directly, without trying
+ // to encode it.
+ expect(server.requests[0].requestBody).to.be.equal(requestObj);
+ });
+ })
+ });
+
+ suite('when debouncing requests', function() {
+ setup(function() {
+ ajax = fixture('DebouncedGet');
+ });
+
+ test('only requests a single resource', function() {
+ ajax._requestOptionsChanged();
+ expect(server.requests[0]).to.be.equal(undefined);
+ ajax._requestOptionsChanged();
+ return timePasses(200).then(function() {
+ expect(server.requests[0]).to.be.ok;
+ });
+ });
+ });
+
+ suite('when a response handler is bound', function() {
+ var responseHandler;
+
+ setup(function() {
+ responseHandler = sinon.spy();
+ ajax.addEventListener('response', responseHandler);
+ });
+
+ test('calls the handler after every response', function() {
+ ajax.generateRequest();
+ ajax.generateRequest();
+
+ server.respond();
+
+ return ajax.lastRequest.completes.then(function() {
+ expect(responseHandler.callCount).to.be.equal(2);
+ });
+ });
+ });
+
+ suite('when the response type is `json`', function() {
+ setup(function() {
+ server.restore();
+ });
+
+ test('finds the JSON on any platform', function() {
+ ajax.url = '../bower.json';
+ request = ajax.generateRequest();
+ return request.completes.then(function() {
+ expect(ajax.lastResponse).to.be.instanceOf(Object);
+ });
+ });
+ });
+
+ suite('when handleAs parameter is `text`', function() {
+
+ test('response type is string', function() {
+ ajax.url = '/responds_to_get_with_json';
+ ajax.handleAs = 'text';
+
+ request = ajax.generateRequest();
+ var promise = request.completes.then(function() {
+ expect(typeof(ajax.lastResponse)).to.be.equal('string');
+ });
+
+ expect(server.requests.length).to.be.equal(1);
+ expect(server.requests[0].requestHeaders['accept']).to.be.equal(
+ 'text/plain');
+ server.respond();
+
+ return promise;
+ });
+
+ });
+
+ suite('when a request fails', function() {
+ test('we give an error with useful details', function() {
+ ajax.url = '/responds_to_get_with_502_error_json';
+ ajax.handleAs = 'json';
+ var eventFired = false;
+ ajax.addEventListener('error', function(event) {
+ expect(event.detail.request).to.be.ok;
+ expect(event.detail.error).to.be.ok;
+ eventFired = true;
+ });
+ var request = ajax.generateRequest();
+ var promise = request.completes.then(function() {
+ throw new Error('Expected the request to fail!');
+ }, function(error) {
+ expect(error).to.be.instanceof(Error);
+ expect(request.succeeded).to.be.eq(false);
+ return timePasses(100);
+ }).then(function() {
+ expect(eventFired).to.be.eq(true);
+ expect(ajax.lastError).to.not.be.eq(null);
+ expect(ajax.lastError.status).to.be.eq(502);
+ expect(ajax.lastError.statusText).to.be.eq("Bad Gateway");
+ expect(ajax.lastError.response).to.be.ok;
+ });
+
+ server.respond();
+
+ return promise;
+ });
+
+ test('with rejectWithRequest the promise chain contains the request and error', function() {
+ ajax.url = '/responds_to_get_with_502_error_json';
+ ajax.handleAs = 'json';
+ ajax.rejectWithRequest = true;
+
+ var request = ajax.generateRequest();
+ var promise = request.completes.then(function() {
+ throw new Error('Expected the request to fail!');
+ }, function(resp) {
+ expect(resp.error).to.be.instanceof(Error);
+ expect(resp.request).to.deep.equal(request);
+ });
+
+ server.respond();
+
+ return promise;
+ });
+
+ test('we give a useful error even when the domain doesn\'t resolve', function() {
+ ajax.url = 'http://nonexistant.example.com/';
+ server.restore();
+ var eventFired = false;
+ ajax.addEventListener('error', function(event) {
+ expect(event.detail.request).to.be.ok;
+ expect(event.detail.error).to.be.ok;
+ eventFired = true;
+ });
+ var request = ajax.generateRequest();
+ var promise = request.completes.then(function() {
+ throw new Error('Expected the request to fail!');
+ }, function(error) {
+ expect(request.succeeded).to.be.eq(false);
+ expect(error).to.not.be.eq(null);
+ return timePasses(100);
+ }).then(function() {
+ expect(eventFired).to.be.eq(true);
+ expect(ajax.lastError).to.not.be.eq(null);
+ });
+
+ server.respond();
+
+ return promise;
+ });
+ });
+
+ suite('when handleAs parameter is `json`', function() {
+
+ test('response type is string', function() {
+ ajax.url = '/responds_to_get_with_json';
+ ajax.handleAs = 'json';
+
+ request = ajax.generateRequest();
+ var promise = request.completes.then(function() {
+ expect(typeof(ajax.lastResponse)).to.be.equal('object');
+ });
+
+ expect(server.requests.length).to.be.equal(1);
+ expect(server.requests[0].requestHeaders['accept']).to.be.equal(
+ 'application/json');
+
+ server.respond();
+
+ return promise;
+ });
+
+ });
+
+ suite('when making a POST over the wire', function() {
+ test('FormData is handled correctly', function() {
+ server.restore();
+ var requestBody = new FormData();
+ requestBody.append('a', 'foo');
+ requestBody.append('b', 'bar');
+
+ var ajax = fixture('RealPost');
+ ajax.body = requestBody;
+ return ajax.generateRequest().completes.then(function() {
+ expect(ajax.lastResponse.headers['Content-Type']).to.match(
+ /^multipart\/form-data; boundary=.*$/);
+
+ expect(ajax.lastResponse.form.a).to.be.equal('foo');
+ expect(ajax.lastResponse.form.b).to.be.equal('bar');
+ });
+ });
+
+ test('json is handled correctly', function() {
+ server.restore();
+ var ajax = fixture('RealPost');
+ ajax.body = JSON.stringify({a: 'foo', b: 'bar'});
+ ajax.contentType = 'application/json';
+ return ajax.generateRequest().completes.then(function() {
+ expect(ajax.lastResponse.headers['Content-Type']).to.match(
+ /^application\/json(;.*)?$/);
+ expect(ajax.lastResponse.json.a).to.be.equal('foo');
+ expect(ajax.lastResponse.json.b).to.be.equal('bar');
+ });
+ });
+
+ test('urlencoded data is handled correctly', function() {
+ server.restore();
+ var ajax = fixture('RealPost');
+ ajax.body = 'a=foo&b=bar';
+ return ajax.generateRequest().completes.then(function() {
+ expect(ajax.lastResponse.headers['Content-Type']).to.match(
+ /^application\/x-www-form-urlencoded(;.*)?$/);
+
+ expect(ajax.lastResponse.form.a).to.be.equal('foo');
+ expect(ajax.lastResponse.form.b).to.be.equal('bar');
+ });
+ });
+
+ test('xml is handled correctly', function() {
+ server.restore();
+ var ajax = fixture('RealPost');
+
+ var xmlDoc = document.implementation.createDocument(
+ null, "foo", null);
+ var node = xmlDoc.createElement("bar");
+ node.setAttribute("name" , "baz");
+ xmlDoc.documentElement.appendChild(node);
+ ajax.body = xmlDoc;
+ return ajax.generateRequest().completes.then(function() {
+ expect(ajax.lastResponse.headers['Content-Type']).to.match(
+ /^application\/xml(;.*)?$/);
+ expect(ajax.lastResponse.data).to.match(
+ /<foo\s*><bar\s+name="baz"\s*\/><\/foo\s*>/);
+ });
+ });
+ });
+
+ suite('when setting timeout', function() {
+ setup(function() {
+ server.restore();
+ });
+
+ test('it is present in the request xhr object', function() {
+ ajax.url = '/responds_to_get_with_json';
+ ajax.timeout = 5000; // 5 Seconds
+
+ request = ajax.generateRequest();
+ expect(request.xhr.timeout).to.be.equal(5000); // 5 Seconds
+ });
+
+ test('it fails once that timeout is reached', function() {
+ var ajax = fixture('Delay');
+ ajax.timeout = 1; // 1 Millisecond
+
+ request = ajax.generateRequest();
+ return request.completes.then(function() {
+ throw new Error('Expected the request to throw an error.');
+ }, function() {
+ expect(request.succeeded).to.be.equal(false);
+ expect(request.xhr.status).to.be.equal(0);
+ expect(request.timedOut).to.be.equal(true);
+ return timePasses(1);
+ }).then(function() {
+ expect(ajax.loading).to.be.equal(false);
+ expect(ajax.lastResponse).to.be.equal(null);
+ expect(ajax.lastError).to.not.be.equal(null);
+ });
+ });
+ });
+
+ suite('when using the bubbles attribute', function() {
+ test('the request and response events should bubble to window', function(done) {
+ server.restore();
+ var total = 0;
+ function incrementTotal() {
+ total++;
+ if (total === 5) {
+ done();
+ }
+ }
+ window.addEventListener('iron-ajax-presend', incrementTotal);
+ window.addEventListener('request', incrementTotal);
+ window.addEventListener('iron-ajax-request', incrementTotal);
+ window.addEventListener('response', incrementTotal);
+ window.addEventListener('iron-ajax-response', incrementTotal);
+ var ajax = fixture('Bubbles')[0];
+ ajax.generateRequest();
+ server.respond();
+ });
+
+ test('the request and error events should bubble to window', function(done) {
+ var total = 0;
+ function incrementTotal() {
+ total++;
+ if (total === 5) {
+ done();
+ }
+ }
+ window.addEventListener('iron-ajax-presend', incrementTotal);
+ window.addEventListener('request', incrementTotal);
+ window.addEventListener('iron-ajax-request', incrementTotal);
+ // NOTE(cdata): This needs to be capturing because Mocha + Firefox
+ // results in the error event being observed too early by the test
+ // runner and failing the test:
+ window.addEventListener('error', incrementTotal, true);
+ window.addEventListener('iron-ajax-error', incrementTotal);
+ var ajax = fixture('Bubbles')[1];
+ ajax.generateRequest();
+ server.respond();
+ });
+ });
+
+ suite('when handling the `iron-ajax-presend` event', function() {
+ setup(function() {
+ server.restore();
+ });
+
+ test('ability to cancel request', function() {
+ var requestSpy = sinon.spy();
+ var promiseSpy = sinon.spy();
+
+ ajax.addEventListener('iron-ajax-presend', function(e) {
+ e.preventDefault();
+ });
+ ajax.addEventListener('iron-ajax-request', requestSpy);
+
+ var request = ajax.generateRequest();
+
+ return request.completes.catch(function(request) {
+ expect(request.aborted).to.be.true;
+ promiseSpy();
+ }).then(function() {
+ expect(promiseSpy).to.be.calledOnce;
+ expect(requestSpy).not.to.be.called;
+ });
+ });
+
+ test('ability to modify the request options', function(done) {
+ ajax.addEventListener('iron-ajax-presend', function(e) {
+ e.detail.options.url += '/test';
+ e.detail.options.headers.authToken = 'a.b.c';
+ });
+ ajax.addEventListener('iron-ajax-request', function(e) {
+ expect(e.detail.options.url).to.equal('/responds_to_get_with_json/test');
+ expect(e.detail.options.headers.authToken).to.equal('a.b.c');
+ done();
+ });
+
+ ajax.generateRequest();
+ });
+ });
+ });
+ </script>
+
+</body>
+</html>
diff --git a/catapult/third_party/polymer/components/iron-ajax/test/iron-request.html b/catapult/third_party/polymer/components/iron-ajax/test/iron-request.html
new file mode 100644
index 00000000..6161bb5f
--- /dev/null
+++ b/catapult/third_party/polymer/components/iron-ajax/test/iron-request.html
@@ -0,0 +1,368 @@
+<!doctype html>
+<!--
+@license
+Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+-->
+<html>
+<head>
+ <title>iron-request</title>
+
+ <script src="../../webcomponentsjs/webcomponents-lite.js"></script>
+ <script src="../../web-component-tester/browser.js"></script>
+
+ <link rel="import" href="../../polymer/polymer.html">
+ <link rel="import" href="../../promise-polyfill/promise-polyfill.html">
+ <link rel="import" href="../iron-request.html">
+</head>
+<body>
+ <test-fixture id="TrivialRequest">
+ <template>
+ <iron-request></iron-request>
+ </template>
+ </test-fixture>
+ <script>
+ suite('<iron-request>', function() {
+ var jsonResponseHeaders;
+ var successfulRequestOptions;
+ var request;
+ var server;
+
+ setup(function() {
+ jsonResponseHeaders = {
+ 'Content-Type': 'application/json'
+ };
+ server = sinon.fakeServer.create();
+ server.respondWith('GET', '/responds_to_get_with_json', [
+ 200,
+ jsonResponseHeaders,
+ '{"success":true}'
+ ]);
+
+ server.respondWith('GET', '/responds_to_get_with_prefixed_json', [
+ 200,
+ jsonResponseHeaders,
+ '])}while(1);</x>{"success":true}'
+ ]);
+
+ server.respondWith('GET', '/responds_to_get_with_500', [
+ 500,
+ {},
+ ''
+ ]);
+
+ server.respondWith('GET', '/responds_to_get_with_100', [
+ 100,
+ {},
+ ''
+ ]);
+
+ server.respondWith('GET', '/responds_to_get_with_0', [
+ 0,
+ jsonResponseHeaders,
+ '{"success":true}'
+ ]);
+
+
+ request = fixture('TrivialRequest');
+ successfulRequestOptions = {
+ url: '/responds_to_get_with_json'
+ };
+
+ synchronousSuccessfulRequestOptions = {
+ url: '/responds_to_get_with_json',
+ async: false,
+ timeout: 100
+ };
+
+ asynchronousSuccessfulRequestOptions = {
+ url: '/responds_to_get_with_json',
+ async: true,
+ timeout: 100
+ };
+ });
+
+ teardown(function() {
+ server.restore();
+ });
+
+ suite('basic usage', function() {
+ test('creates network requests, requiring only `url`', function() {
+ request.send(successfulRequestOptions);
+
+ server.respond();
+
+ expect(request.response).to.be.ok;
+ });
+
+ test('timeout not set if synchronous', function() {
+ request.send(synchronousSuccessfulRequestOptions);
+
+ expect(request.xhr.async).to.be.eql(false);
+ expect(request.xhr.timeout).to.be.eql(undefined);
+ });
+
+ test('timeout set if asynchronous', function() {
+ request.send(asynchronousSuccessfulRequestOptions);
+
+ expect(request.xhr.async).to.be.eql(true);
+ expect(request.xhr.timeout).to.be.eql(100);
+ });
+
+ test('sets async to true by default', function() {
+ request.send(successfulRequestOptions);
+ expect(request.xhr.async).to.be.eql(true);
+ });
+
+ test('can be aborted', function() {
+ request.send(successfulRequestOptions);
+
+ request.abort();
+
+ server.respond();
+
+ return request.completes.then(function() {
+ throw new Error('Request did not abort appropriately!');
+ }).catch(function(e) {
+ expect(request.response).to.not.be.ok;
+ });
+ });
+
+ test('can be aborted with request element', function() {
+ var options = {
+ url: successfulRequestOptions.url,
+ rejectWithRequest: true
+ };
+ request.send(options);
+
+ request.abort();
+
+ server.respond();
+
+ return request.completes.then(function() {
+ throw new Error('Request did not abort appropriately!');
+ }).catch(function(e) {
+ expect(e.error).to.be.instanceof(Error);
+ expect(e.request).to.deep.equal(request);
+ });
+ });
+
+ test('default responseType is text', function() {
+ request.send(successfulRequestOptions);
+ server.respond();
+
+ return request.completes.then(function() {
+ expect(request.response).to.be.an('string')
+ });
+ });
+
+ test('default responseType of text is not applied, when async is false', function() {
+ var options = Object.create(successfulRequestOptions);
+ options.async = false;
+
+ request.send(options);
+ server.respond();
+
+ return request.completes.then(function() {
+ expect(request.xhr.responseType).to.be.empty;
+ });
+ });
+
+ test('responseType can be configured via handleAs option', function() {
+ var options = Object.create(successfulRequestOptions);
+ options.handleAs = 'json';
+
+ request.send(options);
+ expect(server.requests.length).to.be.equal(1);
+ expect(server.requests[0].requestHeaders['accept']).to.be.equal(
+ 'application/json');
+ server.respond();
+
+ return request.completes.then(function() {
+ expect(request.response).to.be.an('object');
+ });
+ });
+
+ test('setting jsonPrefix correctly strips it from the response', function() {
+ var options = {
+ url: '/responds_to_get_with_prefixed_json',
+ handleAs: 'json',
+ jsonPrefix: '])}while(1);</x>'
+ };
+
+ request.send(options);
+ expect(server.requests.length).to.be.equal(1);
+ expect(server.requests[0].requestHeaders['accept']).to.be.equal(
+ 'application/json');
+ server.respond();
+
+ return request.completes.then(function() {
+ expect(request.response).to.deep.eq({success: true});
+ });
+ });
+
+ test('responseType cannot be configured via handleAs option, when async is false', function() {
+ var options = Object.create(successfulRequestOptions);
+ options.handleAs = 'json';
+ options.async = false;
+
+ request.send(options);
+ expect(server.requests.length).to.be.equal(1);
+ expect(server.requests[0].requestHeaders['accept']).to.be.equal(
+ 'application/json');
+ server.respond();
+
+ return request.completes.then(function() {
+ expect(request.response).to.be.a('string');
+ });
+ });
+
+ test('headers are sent up', function() {
+ var options = Object.create(successfulRequestOptions);
+ options.headers = {
+ 'foo': 'bar',
+ 'accept': 'this should override the default'
+ };
+ request.send(options);
+ expect(server.requests.length).to.be.equal(1);
+ var fakeXhr = server.requests[0]
+ expect(fakeXhr.requestHeaders['foo']).to.be.equal(
+ 'bar');
+ expect(fakeXhr.requestHeaders['accept']).to.be.equal(
+ 'this should override the default');
+ });
+
+ test('headers are deduped by lowercasing', function() {
+ var options = Object.create(successfulRequestOptions);
+ options.headers = {
+ 'foo': 'bar',
+ 'Foo': 'bar',
+ 'fOo': 'bar',
+ 'Accept': 'this should also override the default'
+ };
+ request.send(options);
+ expect(server.requests.length).to.be.equal(1);
+ var fakeXhr = server.requests[0]
+ expect(Object.keys(fakeXhr.requestHeaders).length).to.be.equal(2);
+ expect(fakeXhr.requestHeaders['foo']).to.be.equal(
+ 'bar');
+ expect(fakeXhr.requestHeaders['accept']).to.be.equal(
+ 'this should also override the default');
+ });
+ });
+
+ suite('special cases', function() {
+ test('treats status code 0 as success, though the outcome is ambiguous', function() {
+ // Note: file:// status code will probably be 0 no matter what happened.
+ request.send({
+ url: '/responds_to_get_with_0'
+ });
+
+ server.respond();
+
+ expect(request.succeeded).to.be.equal(true);
+ });
+
+ test('special form characters', function() {
+ var testCases = [
+ {
+ test: null,
+ answer: ''
+ },
+ {
+ test: undefined,
+ answer: ''
+ },
+ {
+ test: NaN,
+ answer: 'NaN'
+ },
+ {
+ test: new String('\n\r\n\r'),
+ answer: '%0D%0A%0D%0A%0D' // \r\n\r\n\r
+ },
+ {
+ test: 0,
+ answer: '0'
+ },
+ {
+ test: new String('hello world'),
+ answer: 'hello+world'
+ }
+ ];
+
+ var testCase;
+ for (var i = 0; i < testCases.length; i++) {
+ testCase = testCases[i];
+ var encoded = request._wwwFormUrlEncodePiece(testCase.test);
+
+ expect(encoded).to.be.equal(testCase.answer);
+ }
+ });
+ });
+
+ suite('errors', function() {
+ test('treats status codes between 1 and 199 as errors', function() {
+ request.send({
+ url: '/responds_to_get_with_100'
+ });
+
+ server.respond();
+
+ expect(request.succeeded).to.be.equal(false);
+ });
+
+ test('treats status codes between 300 and ∞ as errors', function() {
+ request.send({
+ url: '/responds_to_get_with_500'
+ });
+
+ server.respond();
+
+ expect(request.succeeded).to.be.equal(false);
+ });
+ });
+
+ suite('status codes', function() {
+ test('status and statusText is set after a ambiguous request', function() {
+ request.send({
+ url: '/responds_to_get_with_0'
+ });
+
+ server.respond();
+
+ expect(request.status).to.be.equal(0);
+ expect(request.statusText).to.be.equal('');
+ });
+
+ test('status and statusText is set after a request that succeeded', function() {
+ request.send({
+ url: '/responds_to_get_with_json'
+ });
+
+ server.respond();
+
+ expect(request.status).to.be.equal(200);
+ expect(request.statusText).to.be.equal('OK');
+ });
+
+ test('status and statusText is set after a request that failed', function() {
+ request.send({
+ url: '/responds_to_get_with_500'
+ });
+
+ server.respond();
+
+ expect(request.status).to.be.equal(500);
+ expect(request.statusText).to.be.equal('Internal Server Error');
+ });
+ });
+ });
+ </script>
+
+</body>
+</html>