index.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. var window = require("global/window")
  2. var test = require("tape")
  3. var forEach = require("for-each")
  4. var xhr = require("../index.js")
  5. test("constructs and calls callback without throwing", { timeout: 500 }, function(assert) {
  6. xhr({}, function(err, resp, body) {
  7. assert.ok(true, "got here")
  8. assert.end()
  9. })
  10. })
  11. test("[func] Can GET a url (cross-domain)", { timeout: 2000 }, function(assert) {
  12. xhr({
  13. uri: "http://www.mocky.io/v2/55a02cb72651260b1a94f024",
  14. useXDR: true
  15. }, function(err, resp, body) {
  16. assert.ifError(err, "no err")
  17. assert.equal(resp.statusCode, 200)
  18. assert.equal(typeof resp.rawRequest, "object")
  19. assert.notEqual(resp.body.length, 0)
  20. assert.equal(resp.body, '{"a":1}')
  21. assert.notEqual(body.length, 0)
  22. assert.end()
  23. })
  24. })
  25. test("[func] Returns http error responses like npm's request (cross-domain)", { timeout: 2000 }, function(assert) {
  26. if (!window.XDomainRequest) {
  27. xhr({
  28. uri: "http://www.mocky.io/v2/55a02d63265126221a94f025",
  29. }, function(err, resp, body) {
  30. assert.ifError(err, "no err")
  31. assert.equal(resp.statusCode, 404)
  32. assert.equal(typeof resp.rawRequest, "object")
  33. assert.end()
  34. })
  35. } else {
  36. assert.end();
  37. }
  38. })
  39. test("[func] Request to domain with not allowed cross-domain", { timeout: 2000 }, function(assert) {
  40. xhr({
  41. uri: "http://www.mocky.io/v2/57bb70c21000002f175850bd",
  42. }, function(err, resp, body) {
  43. assert.ok(err instanceof Error, "should return error")
  44. assert.equal(resp.statusCode, 0)
  45. assert.equal(typeof resp.rawRequest, "object")
  46. assert.end()
  47. })
  48. })
  49. test("[func] Returns a falsy body for 2xx responses", { timeout: 500 }, function(assert) {
  50. assert.plan(8)
  51. xhr({
  52. uri: "/mock/no-content/200"
  53. }, function(err, resp, body) {
  54. assert.notOk(body, "body should be falsy")
  55. assert.equal(resp.statusCode, 200)
  56. })
  57. xhr({
  58. uri: "/mock/no-content/201"
  59. }, function(err, resp, body) {
  60. assert.notOk(body, "body should be falsy")
  61. assert.equal(resp.statusCode, 201)
  62. })
  63. xhr({
  64. uri: "/mock/no-content/204"
  65. }, function(err, resp, body) {
  66. assert.notOk(body, "body should be falsy")
  67. assert.equal(resp.statusCode, 204)
  68. })
  69. xhr({
  70. uri: "/mock/no-content/205"
  71. }, function(err, resp, body) {
  72. assert.notOk(body, "body should be falsy")
  73. assert.equal(resp.statusCode, 205)
  74. })
  75. })
  76. test("[func] Calls the callback at most once even if error is thrown issue #127", { timeout: 500 }, function(assert) {
  77. //double call happened in chrome
  78. var count = 0;
  79. setTimeout(function() {
  80. assert.ok(count <= 1, "expected at most one call")
  81. assert.end()
  82. }, 100)
  83. try {
  84. xhr({
  85. uri: "instanterror://foo"
  86. }, function(err, resp, body) {
  87. count++;
  88. throw Error("dummy error")
  89. })
  90. } catch(e){}
  91. })
  92. test("[func] Times out to an error ", { timeout: 500 }, function(assert) {
  93. xhr({
  94. timeout: 1,
  95. uri: "/mock/timeout"
  96. }, function(err, resp, body) {
  97. assert.ok(err instanceof Error, "should return error")
  98. assert.equal(err.message, "XMLHttpRequest timeout")
  99. assert.equal(err.code, "ETIMEDOUT")
  100. assert.equal(resp.statusCode, 0)
  101. assert.end()
  102. })
  103. })
  104. test("withCredentials option", { timeout: 500 }, function(assert) {
  105. if (!window.XDomainRequest) {
  106. var req = xhr({}, function() {})
  107. assert.ok(!req.withCredentials,
  108. "withCredentials not true"
  109. )
  110. req = xhr({
  111. withCredentials: true
  112. }, function() {})
  113. assert.ok(
  114. req.withCredentials,
  115. "withCredentials set to true"
  116. )
  117. }
  118. assert.end()
  119. })
  120. test("withCredentials ignored when using synchronous requests", { timeout: 500 }, function(assert) {
  121. if (!window.XDomainRequest) {
  122. var req = xhr({
  123. withCredentials: true,
  124. sync: true
  125. }, function() {})
  126. assert.ok(!req.withCredentials,
  127. "sync overrides withCredentials"
  128. )
  129. }
  130. assert.end()
  131. })
  132. test("XDR usage (run on IE8 or 9)", { timeout: 500 }, function(assert) {
  133. var req = xhr({
  134. useXDR: true,
  135. uri: window.location.href,
  136. }, function() {})
  137. assert.ok(!window.XDomainRequest || window.XDomainRequest === req.constructor,
  138. "Uses XDR when told to"
  139. )
  140. if (!!window.XDomainRequest) {
  141. assert.throws(function() {
  142. xhr({
  143. useXDR: true,
  144. uri: window.location.href,
  145. headers: {
  146. "foo": "bar"
  147. }
  148. }, function() {})
  149. }, true, "Throws when trying to send headers with XDR")
  150. }
  151. assert.end()
  152. })
  153. test("handles errorFunc call with no arguments provided", { timeout: 500 }, function(assert) {
  154. var req = xhr({}, function(err) {
  155. assert.ok(err instanceof Error, "callback should get an error")
  156. assert.equal(err.message, "Unknown XMLHttpRequest Error", "error message incorrect")
  157. })
  158. assert.doesNotThrow(function() {
  159. req.onerror()
  160. }, "should not throw when error handler called without arguments")
  161. assert.end()
  162. })
  163. test("constructs and calls callback without throwing", { timeout: 500 }, function(assert) {
  164. assert.throws(function() {
  165. xhr({})
  166. }, "callback is not optional")
  167. assert.end()
  168. })
  169. if (!window.XDomainRequest) {
  170. var methods = ["get", "put", "post", "patch"]
  171. } else {
  172. var methods = ["get", "post"]
  173. }
  174. test("[func] xhr[method] get, put, post, patch", { timeout: 500 }, function(assert) {
  175. var i = 0
  176. forEach(methods, function(method) {
  177. xhr[method]({
  178. uri: "/mock/200ok"
  179. }, function(err, resp, body) {
  180. i++
  181. assert.ifError(err, "no err")
  182. assert.equal(resp.statusCode, 200)
  183. assert.equal(resp.method, method.toUpperCase())
  184. if (i === methods.length) assert.end()
  185. })
  186. })
  187. })
  188. test("xhr[method] get, put, post, patch with url shorthands", { timeout: 500 }, function(assert) {
  189. var i = 0
  190. forEach(methods, function(method) {
  191. var req = xhr[method]("/some-test", function() {})
  192. i++
  193. assert.equal(req.method, method.toUpperCase())
  194. if (i === methods.length) assert.end()
  195. })
  196. })
  197. test("[func] sends options.body as json body when options.json === true", { timeout: 500 }, function(assert) {
  198. xhr.post("/mock/echo", {
  199. json: true,
  200. body: {
  201. foo: "bar"
  202. }
  203. }, function(err, resp, body) {
  204. assert.equal(resp.rawRequest.headers["Content-Type"], "application/json")
  205. assert.deepEqual(body, {
  206. foo: "bar"
  207. })
  208. assert.end()
  209. })
  210. })
  211. test("[func] doesn't freak out when json option is false", { timeout: 500 }, function(assert) {
  212. xhr.post("/mock/echo", {
  213. json: false,
  214. body: "{\"a\":1}"
  215. }, function(err, resp, body) {
  216. assert.notEqual(resp.rawRequest.headers["Content-Type"], "application/json")
  217. assert.equal(body, "{\"a\":1}")
  218. assert.end()
  219. })
  220. })
  221. test("[func] sends options.json as body when it's not a boolean", { timeout: 500 }, function(assert) {
  222. xhr.post("/mock/echo", {
  223. json: {
  224. foo: "bar"
  225. }
  226. }, function(err, resp, body) {
  227. assert.equal(resp.rawRequest.headers["Content-Type"], "application/json")
  228. assert.deepEqual(body, {
  229. foo: "bar"
  230. })
  231. assert.end()
  232. })
  233. })
  234. test("xhr[method] get, put, post, patch with url shorthands and options", { timeout: 500 }, function(assert) {
  235. var i = 0
  236. forEach(methods, function(method) {
  237. var req = xhr[method]("/some-test", {
  238. headers: {
  239. foo: 'bar'
  240. }
  241. }, function(err, resp, body) {
  242. i++
  243. assert.equal(resp.rawRequest.headers.foo, 'bar')
  244. assert.equal(resp.method, method.toUpperCase())
  245. if (i === methods.length) assert.end()
  246. })
  247. })
  248. })
  249. if (!window.XDomainRequest) {
  250. test("[func] xhr.head", function(assert) {
  251. xhr.head({
  252. uri: "/mock/200ok",
  253. }, function(err, resp, body) {
  254. assert.ifError(err, "no err")
  255. assert.equal(resp.statusCode, 200)
  256. assert.equal(resp.method, "HEAD")
  257. assert.notOk(resp.body)
  258. assert.end()
  259. })
  260. })
  261. test("xhr.head url shorthand", { timeout: 500 }, function(assert) {
  262. xhr.head("/mock/200ok", function(err, resp, body) {
  263. assert.equal(resp.method, "HEAD")
  264. assert.end()
  265. })
  266. })
  267. test("[func] xhr.del", { timeout: 500 }, function(assert) {
  268. xhr.del({
  269. uri: "/mock/200ok"
  270. }, function(err, resp, body) {
  271. assert.ifError(err, "no err")
  272. assert.equal(resp.statusCode, 200)
  273. assert.equal(resp.method, "DELETE")
  274. assert.end()
  275. })
  276. })
  277. test("xhr.del url shorthand", { timeout: 500 }, function(assert) {
  278. xhr.del("/mock/200ok", function(err, resp, body) {
  279. assert.equal(resp.method, "DELETE")
  280. assert.end()
  281. })
  282. })
  283. }
  284. test("url signature without object", { timeout: 500 }, function(assert) {
  285. xhr("/some-test", function(err, resp, body) {
  286. assert.equal(resp.url, '/some-test')
  287. assert.end()
  288. })
  289. })
  290. test("url signature with object", { timeout: 500 }, function(assert) {
  291. xhr("/some-test", {
  292. headers: {
  293. "foo": "bar"
  294. }
  295. }, function(err, resp, body) {
  296. assert.equal(resp.url, '/some-test')
  297. assert.equal(resp.rawRequest.headers.foo, 'bar')
  298. assert.end()
  299. })
  300. })
  301. test("aborting XHR immediately prevents callback from being called", { timeout: 500 }, function(assert) {
  302. var req = xhr({ uri: "/mock/200ok" }, function(err, response) {
  303. assert.fail('this callback should not be called');
  304. });
  305. req.abort();
  306. setTimeout(function() {
  307. assert.end()
  308. }, 2)
  309. })
  310. test("aborting XHR asynchronously still prevents callback from being called", { timeout: 500 }, function(assert) {
  311. var req = xhr({ uri: "/mock/timeout" }, function(err, response) {
  312. assert.fail('this callback should not be called');
  313. });
  314. setTimeout(function() {
  315. req.abort();
  316. }, 0)
  317. setTimeout(function() {
  318. assert.end()
  319. }, 2)
  320. })
  321. test("XHR can be overridden", { timeout: 500 }, function(assert) {
  322. var xhrs = 0
  323. var noop = function() {}
  324. var fakeXHR = function() {
  325. xhrs++
  326. this.open = this.send = noop
  327. }
  328. var xdrs = 0
  329. var fakeXDR = function() {
  330. xdrs++
  331. this.open = this.send = noop
  332. }
  333. xhr.XMLHttpRequest = fakeXHR
  334. xhr({}, function() {})
  335. assert.equal(xhrs, 1, "created the custom XHR")
  336. xhr.XDomainRequest = fakeXDR
  337. xhr({
  338. useXDR: true
  339. }, function() {});
  340. assert.equal(xdrs, 1, "created the custom XDR")
  341. assert.end()
  342. })