UNPKG

rest-boubou

Version:

RESTful HTTP client library

243 lines (228 loc) 8.05 kB
/* * Copyright 2012-2014 the original author or authors * @license MIT, see LICENSE.txt for details * * @author Scott Andrews */ (function (buster, define) { 'use strict'; var assert, refute, fail, failOnThrow; assert = buster.assertions.assert; refute = buster.assertions.refute; fail = buster.assertions.fail; failOnThrow = buster.assertions.failOnThrow; define('rest/client/xhr-test', function (require) { var xhr, rest, xhrFallback, when, client; xhr = require('rest/client/xhr'); rest = require('rest'); xhrFallback = require('rest/interceptor/ie/xhr'); when = require('when'); // use xhrFallback when XHR is not native client = !XMLHttpRequest ? xhr.wrap(xhrFallback) : xhr; buster.testCase('rest/client/xhr', { 'should make a GET by default': function () { var request = { path: '/' }; return client(request).then(function (response) { var xhr, name; xhr = response.raw; assert.same(request, response.request); assert.equals(response.request.method, 'GET'); assert.equals(xhr.responseText, response.entity); assert.equals(xhr.status, response.status.code); assert.equals(xhr.statusText, response.status.text); for (name in response.headers) { /*jshint forin:false */ assert.equals(xhr.getResponseHeader(name), response.headers[name]); } refute(request.canceled); }).otherwise(fail); }, 'should make an explicit GET': function () { var request = { path: '/', method: 'GET' }; return client(request).then(function (response) { var xhr, name; xhr = response.raw; assert.same(request, response.request); assert.equals(response.request.method, 'GET'); assert.equals(xhr.responseText, response.entity); assert.equals(xhr.status, response.status.code); assert.equals(xhr.statusText, response.status.text); for (name in response.headers) { /*jshint forin:false */ assert.equals(xhr.getResponseHeader(name), response.headers[name]); } refute(request.canceled); }).otherwise(fail); }, 'should make a POST with an entity': function () { var request = { path: '/', entity: 'hello world' }; return client(request).then(function (response) { var xhr, name; xhr = response.raw; assert.same(request, response.request); assert.equals(response.request.method, 'POST'); assert.equals(xhr.responseText, response.entity); assert.equals(xhr.status, response.status.code); assert.equals(xhr.statusText, response.status.text); for (name in response.headers) { /*jshint forin:false */ assert.equals(xhr.getResponseHeader(name), response.headers[name]); } refute(request.canceled); }).otherwise(fail); }, 'should make an explicit POST with an entity': function () { var request = { path: '/', entity: 'hello world', method: 'POST' }; return client(request).then(function (response) { var xhr, name; xhr = response.raw; assert.same(request, response.request); assert.equals(response.request.method, 'POST'); assert.equals(xhr.responseText, response.entity); assert.equals(xhr.status, response.status.code); assert.equals(xhr.statusText, response.status.text); for (name in response.headers) { /*jshint forin:false */ assert.equals(xhr.getResponseHeader(name), response.headers[name]); } refute(request.canceled); }).otherwise(fail); }, 'should mixin additional properties': { requiresSupportFor: { timeout: XMLHttpRequest && 'timeout' in new XMLHttpRequest() }, '': function () { var request = { path: '/', mixin: { timeout: 1000, foo: 'bar' } }; return client(request).then(function (response) { var xhr = response.raw; assert.equals(xhr.timeout, 1000); refute.equals(xhr.foo, 'bar'); }).otherwise(function (err) { fail(JSON.stringify(err)); }); } }, '//should abort the request if canceled': function (done) { // TODO find an endpoint that takes a bit to respond, cached files may return synchronously // this test misbehavies in IE6, the response is recieved before the request can cancel var request = { path: '/wait/' + new Date().getTime() }; when.all([ client(request).then( fail, failOnThrow(function (response) { assert(request.canceled); try { // accessing 'status' will throw in older Firefox assert.same(0, response.raw.status); } catch (e) { // ignore } // this assertion is true in every browser except for IE 6 // assert.same(XMLHttpRequest.UNSENT || 0, response.raw.readyState); assert(response.raw.readyState <= 3); }) ), when({}, function () { // push into when's nextTick resolution refute(request.canceled); request.cancel(); }) ]).then(done, done); }, '//should propogate request errors': function () { // TODO follow up with Sauce Labs // this test is valid, but fails with sauce as their proxy returns a 400 var request = { path: 'http://localhost:1234' }; return client(request).then( fail, failOnThrow(function (response) { assert.same('loaderror', response.error); }) ); }, 'should not make a request that has already been canceled': function () { var request = { canceled: true, path: '/' }; return client(request).then( fail, failOnThrow(function (response) { assert.same(request, response.request); assert(request.canceled); assert.same('precanceled', response.error); }) ); }, 'should reject if an XHR impl is not available': { requiresSupportFor: { 'no-xhr': !window.XMLHttpRequest }, '': function () { var request = { path: '/' }; return xhr(request).then( fail, failOnThrow(function (response) { assert.same(request, response.request); assert.same('xhr-not-available', response.error); }) ); } }, 'should normalize a string to a request object': function () { return client('/').then(function (response) { assert.same('/', response.request.path); }).otherwise(fail); }, 'should be the default client': function () { rest.resetDefaultClient(); assert.same(xhr, rest.getDefaultClient()); }, 'should support interceptor wrapping': function () { assert(typeof xhr.wrap === 'function'); }, 'should return a ResponsePromise': function () { assert.isFunction(client().entity); }, 'should ignore a "Content-Type: multipart/form-data" header': { requiresSupportFor: { spyxhr: (function () { // some browsers (IE6) won't allow the XHR to be spied try { var xhr = new XMLHttpRequest(); xhr.setRequestHeader = function () {}; return true; } catch (e) { return false; } }()) }, '': function () { function XMLHttpRequestSpy() { var xhr = new XMLHttpRequest(); xhr.requestHeaders = {}; var setRequestHeader = xhr.setRequestHeader; xhr.setRequestHeader = function (header, value) { xhr.requestHeaders[header] = value; return setRequestHeader.apply(xhr, arguments); }; return xhr; } return client({ engine: XMLHttpRequestSpy, path: '/', headers: { 'Content-Type': 'multipart/form-data' } }).then(function (response) { refute('Content-Type' in response.raw.requestHeaders); }); } } }); }); }( this.buster || require('buster'), typeof define === 'function' && define.amd ? define : function (id, factory) { var packageName = id.split(/[\/\-]/)[0], pathToRoot = id.replace(/[^\/]+/g, '..'); pathToRoot = pathToRoot.length > 2 ? pathToRoot.substr(3) : pathToRoot; factory(function (moduleId) { return require(moduleId.indexOf(packageName) === 0 ? pathToRoot + moduleId.substr(packageName.length) : moduleId); }); } // Boilerplate for AMD and Node ));