wpa_cli_web 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. data/.bowerrc +3 -0
  2. data/lib/wpa_cli_web.rb +19 -31
  3. data/lib/wpa_cli_web/public/bower_components/house-style/.bower.json +14 -0
  4. data/lib/wpa_cli_web/public/bower_components/house-style/.bowerrc +3 -0
  5. data/lib/wpa_cli_web/public/bower_components/house-style/.gitignore +2 -0
  6. data/lib/wpa_cli_web/public/bower_components/house-style/Gemfile +6 -0
  7. data/lib/wpa_cli_web/public/bower_components/house-style/Gruntfile.js +99 -0
  8. data/lib/wpa_cli_web/public/bower_components/house-style/Guardfile +19 -0
  9. data/lib/wpa_cli_web/public/bower_components/house-style/bower.json +7 -0
  10. data/lib/wpa_cli_web/public/bower_components/house-style/bower_components/normalize-css/LICENSE.md +19 -0
  11. data/lib/wpa_cli_web/public/bower_components/house-style/bower_components/normalize-css/README.md +49 -0
  12. data/lib/wpa_cli_web/public/bower_components/house-style/bower_components/normalize-css/bower.json +23 -0
  13. data/lib/wpa_cli_web/public/bower_components/house-style/bower_components/normalize-css/normalize.css +396 -0
  14. data/lib/wpa_cli_web/public/bower_components/house-style/house-style.css +860 -0
  15. data/lib/wpa_cli_web/public/bower_components/house-style/house-style.min.css +1 -0
  16. data/lib/wpa_cli_web/public/bower_components/house-style/modules/base/base.css +37 -0
  17. data/lib/wpa_cli_web/public/bower_components/house-style/modules/button/button.css +26 -0
  18. data/lib/wpa_cli_web/public/bower_components/house-style/modules/grid/grid.css +151 -0
  19. data/lib/wpa_cli_web/public/bower_components/house-style/modules/grid/grid.png +0 -0
  20. data/lib/wpa_cli_web/public/bower_components/house-style/modules/grid/images.html +208 -0
  21. data/lib/wpa_cli_web/public/bower_components/house-style/modules/grid/index.html +141 -0
  22. data/lib/wpa_cli_web/public/bower_components/house-style/modules/loading/index.html +22 -0
  23. data/lib/wpa_cli_web/public/bower_components/house-style/modules/loading/loading.css +41 -0
  24. data/lib/wpa_cli_web/public/bower_components/house-style/modules/loading/spinner.svg +11 -0
  25. data/lib/wpa_cli_web/public/bower_components/house-style/modules/masthead/bbc-blocks-white.png +0 -0
  26. data/lib/wpa_cli_web/public/bower_components/house-style/modules/masthead/index.html +20 -0
  27. data/lib/wpa_cli_web/public/bower_components/house-style/modules/masthead/masthead.css +23 -0
  28. data/lib/wpa_cli_web/public/bower_components/house-style/modules/panel/panel.css +71 -0
  29. data/lib/wpa_cli_web/public/bower_components/house-style/modules/project-header/index.html +22 -0
  30. data/lib/wpa_cli_web/public/bower_components/house-style/modules/project-header/project-header.css +37 -0
  31. data/lib/wpa_cli_web/public/bower_components/house-style/modules/table/index.html +26 -0
  32. data/lib/wpa_cli_web/public/bower_components/house-style/modules/table/table.css +6 -0
  33. data/lib/wpa_cli_web/public/bower_components/house-style/modules/transitions/transitions.css +11 -0
  34. data/lib/wpa_cli_web/public/bower_components/house-style/package.json +21 -0
  35. data/lib/wpa_cli_web/public/bower_components/house-style/vendor/prefixfree.min.js +5 -0
  36. data/lib/wpa_cli_web/public/bower_components/normalize-css/.bower.json +21 -0
  37. data/lib/wpa_cli_web/public/bower_components/normalize-css/LICENSE.md +19 -0
  38. data/lib/wpa_cli_web/public/bower_components/normalize-css/README.md +49 -0
  39. data/lib/wpa_cli_web/public/bower_components/normalize-css/bower.json +12 -0
  40. data/lib/wpa_cli_web/public/bower_components/normalize-css/normalize.css +396 -0
  41. data/lib/wpa_cli_web/public/bower_components/qwery/.bower.json +14 -0
  42. data/lib/wpa_cli_web/public/bower_components/qwery/.gitignore +3 -0
  43. data/lib/wpa_cli_web/public/bower_components/qwery/.travis.yml +10 -0
  44. data/lib/wpa_cli_web/public/bower_components/qwery/LICENSE +7 -0
  45. data/lib/wpa_cli_web/public/bower_components/qwery/Makefile +6 -0
  46. data/lib/wpa_cli_web/public/bower_components/qwery/README.md +167 -0
  47. data/lib/wpa_cli_web/public/bower_components/qwery/config/smoosh.json +35 -0
  48. data/lib/wpa_cli_web/public/bower_components/qwery/integration/ender.js +1033 -0
  49. data/lib/wpa_cli_web/public/bower_components/qwery/integration/integration.html +26 -0
  50. data/lib/wpa_cli_web/public/bower_components/qwery/mobile/ender.js +62 -0
  51. data/lib/wpa_cli_web/public/bower_components/qwery/mobile/package.json +14 -0
  52. data/lib/wpa_cli_web/public/bower_components/qwery/mobile/qwery-mobile.js +79 -0
  53. data/lib/wpa_cli_web/public/bower_components/qwery/mobile/qwery-mobile.min.js +7 -0
  54. data/lib/wpa_cli_web/public/bower_components/qwery/mobile/src/mobile.js +72 -0
  55. data/lib/wpa_cli_web/public/bower_components/qwery/package.json +25 -0
  56. data/lib/wpa_cli_web/public/bower_components/qwery/pseudos/package.json +17 -0
  57. data/lib/wpa_cli_web/public/bower_components/qwery/pseudos/qwery-pseudos.js +106 -0
  58. data/lib/wpa_cli_web/public/bower_components/qwery/pseudos/qwery-pseudos.min.js +7 -0
  59. data/lib/wpa_cli_web/public/bower_components/qwery/pseudos/src/pseudos.js +99 -0
  60. data/lib/wpa_cli_web/public/bower_components/qwery/qwery.js +369 -0
  61. data/lib/wpa_cli_web/public/bower_components/qwery/qwery.min.js +7 -0
  62. data/lib/wpa_cli_web/public/bower_components/qwery/src/copyright.js +6 -0
  63. data/lib/wpa_cli_web/public/bower_components/qwery/src/ender.js +62 -0
  64. data/lib/wpa_cli_web/public/bower_components/qwery/src/qwery.js +362 -0
  65. data/lib/wpa_cli_web/public/bower_components/qwery/tests/W3C-Selector-tests.html +1372 -0
  66. data/lib/wpa_cli_web/public/bower_components/qwery/tests/benchmarks.html +220 -0
  67. data/lib/wpa_cli_web/public/bower_components/qwery/tests/index.html +132 -0
  68. data/lib/wpa_cli_web/public/bower_components/qwery/tests/mobile.html +58 -0
  69. data/lib/wpa_cli_web/public/bower_components/qwery/tests/phantom.js +43 -0
  70. data/lib/wpa_cli_web/public/bower_components/qwery/tests/test-env.js +25 -0
  71. data/lib/wpa_cli_web/public/bower_components/qwery/tests/tests.js +533 -0
  72. data/lib/wpa_cli_web/public/bower_components/qwery/vendor/nw.js +1680 -0
  73. data/lib/wpa_cli_web/public/bower_components/qwery/vendor/sink.css +79 -0
  74. data/lib/wpa_cli_web/public/bower_components/qwery/vendor/sink.js +181 -0
  75. data/lib/wpa_cli_web/public/bower_components/qwery/vendor/sizzle.js +1400 -0
  76. data/lib/wpa_cli_web/public/bower_components/reqwest/.bower.json +14 -0
  77. data/lib/wpa_cli_web/public/bower_components/reqwest/.gitignore +1 -0
  78. data/lib/wpa_cli_web/public/bower_components/reqwest/.jshintrc +61 -0
  79. data/lib/wpa_cli_web/public/bower_components/reqwest/Makefile +8 -0
  80. data/lib/wpa_cli_web/public/bower_components/reqwest/README.md +308 -0
  81. data/lib/wpa_cli_web/public/bower_components/reqwest/build.json +74 -0
  82. data/lib/wpa_cli_web/public/bower_components/reqwest/make/tests.js +89 -0
  83. data/lib/wpa_cli_web/public/bower_components/reqwest/package.json +27 -0
  84. data/lib/wpa_cli_web/public/bower_components/reqwest/reqwest.js +565 -0
  85. data/lib/wpa_cli_web/public/bower_components/reqwest/reqwest.min.js +7 -0
  86. data/lib/wpa_cli_web/public/bower_components/reqwest/src/copyright.js +6 -0
  87. data/lib/wpa_cli_web/public/bower_components/reqwest/src/ender.js +26 -0
  88. data/lib/wpa_cli_web/public/bower_components/reqwest/src/reqwest.js +559 -0
  89. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/ender.js +117 -0
  90. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/fixtures/badfixtures.xml +1 -0
  91. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/fixtures/fixtures.html +1 -0
  92. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/fixtures/fixtures.js +1 -0
  93. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/fixtures/fixtures.json +1 -0
  94. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/fixtures/fixtures.xml +1 -0
  95. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/fixtures/fixtures_jsonp.jsonp +1 -0
  96. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/fixtures/fixtures_jsonp2.jsonp +1 -0
  97. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/fixtures/fixtures_jsonp3.jsonp +1 -0
  98. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/fixtures/fixtures_jsonp_multi.jsonp +1 -0
  99. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/fixtures/fixtures_jsonp_multi_b.jsonp +1 -0
  100. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/fixtures/fixtures_jsonp_multi_c.jsonp +1 -0
  101. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/fixtures/fixtures_with_prefix.json +1 -0
  102. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/fixtures/invalidJSON.json +5 -0
  103. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/tests.html +105 -0
  104. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/tests.js +1723 -0
  105. data/lib/wpa_cli_web/views/access_points.erb +5 -0
  106. data/lib/wpa_cli_web/views/access_points_list.erb +19 -0
  107. data/lib/wpa_cli_web/views/layout.erb +141 -0
  108. data/lib/wpa_cli_web/views/networks_edit.erb +15 -0
  109. data/lib/wpa_cli_web/views/restart.erb +7 -0
  110. data/lib/wpa_cli_web/views/restarting.erb +14 -0
  111. data/wpa_cli_web.gemspec +1 -1
  112. metadata +111 -2
@@ -0,0 +1,117 @@
1
+ /*!
2
+ * Ender: open module JavaScript framework (client-lib)
3
+ * copyright Dustin Diaz & Jacob Thornton 2011-2012 (@ded @fat)
4
+ * http://ender.no.de
5
+ * License MIT
6
+ */
7
+ (function (context) {
8
+
9
+ // a global object for node.js module compatiblity
10
+ // ============================================
11
+
12
+ context['global'] = context
13
+
14
+ // Implements simple module system
15
+ // losely based on CommonJS Modules spec v1.1.1
16
+ // ============================================
17
+
18
+ var modules = {}
19
+ , old = context['$']
20
+ , oldRequire = context['require']
21
+ , oldProvide = context['provide']
22
+
23
+ function require (identifier) {
24
+ // modules can be required from ender's build system, or found on the window
25
+ var module = modules['$' + identifier] || window[identifier]
26
+ if (!module) throw new Error("Ender Error: Requested module '" + identifier + "' has not been defined.")
27
+ return module
28
+ }
29
+
30
+ function provide (name, what) {
31
+ return (modules['$' + name] = what)
32
+ }
33
+
34
+ context['provide'] = provide
35
+ context['require'] = require
36
+
37
+ function aug(o, o2) {
38
+ for (var k in o2) k != 'noConflict' && k != '_VERSION' && (o[k] = o2[k])
39
+ return o
40
+ }
41
+
42
+ /**
43
+ * main Ender return object
44
+ * @constructor
45
+ * @param {Array|Node|string} s a CSS selector or DOM node(s)
46
+ * @param {Array.|Node} r a root node(s)
47
+ */
48
+ function Ender(s, r) {
49
+ var elements
50
+ , i
51
+
52
+ this.selector = s
53
+ // string || node || nodelist || window
54
+ if (typeof s == 'undefined') {
55
+ elements = []
56
+ this.selector = ''
57
+ } else if (typeof s == 'string' || s.nodeName || (s.length && 'item' in s) || s == window) {
58
+ elements = ender._select(s, r)
59
+ } else {
60
+ elements = isFinite(s.length) ? s : [s]
61
+ }
62
+ this.length = elements.length
63
+ for (i = this.length; i--;) this[i] = elements[i]
64
+ }
65
+
66
+ /**
67
+ * @param {function(el, i, inst)} fn
68
+ * @param {Object} opt_scope
69
+ * @returns {Ender}
70
+ */
71
+ Ender.prototype['forEach'] = function (fn, opt_scope) {
72
+ var i, l
73
+ // opt out of native forEach so we can intentionally call our own scope
74
+ // defaulting to the current item and be able to return self
75
+ for (i = 0, l = this.length; i < l; ++i) i in this && fn.call(opt_scope || this[i], this[i], i, this)
76
+ // return self for chaining
77
+ return this
78
+ }
79
+
80
+ Ender.prototype.$ = ender // handy reference to self
81
+
82
+
83
+ function ender(s, r) {
84
+ return new Ender(s, r)
85
+ }
86
+
87
+ ender['_VERSION'] = '0.4.3-dev'
88
+
89
+ ender.fn = Ender.prototype // for easy compat to jQuery plugins
90
+
91
+ ender.ender = function (o, chain) {
92
+ aug(chain ? Ender.prototype : ender, o)
93
+ }
94
+
95
+ ender._select = function (s, r) {
96
+ if (typeof s == 'string') return (r || document).querySelectorAll(s)
97
+ if (s.nodeName) return [s]
98
+ return s
99
+ }
100
+
101
+
102
+ // use callback to receive Ender's require & provide
103
+ ender.noConflict = function (callback) {
104
+ context['$'] = old
105
+ if (callback) {
106
+ context['provide'] = oldProvide
107
+ context['require'] = oldRequire
108
+ callback(require, provide, this)
109
+ }
110
+ return this
111
+ }
112
+
113
+ if (typeof module !== 'undefined' && module.exports) module.exports = ender
114
+ // use subscript notation as extern for Closure compilation
115
+ context['ender'] = context['$'] = context['ender'] || ender
116
+
117
+ }(this));
@@ -0,0 +1 @@
1
+ ><><>Not a valid xml document<><><
@@ -0,0 +1 @@
1
+ <root><boosh>boosh</boosh></root>
@@ -0,0 +1 @@
1
+ reqwest_0({ "boosh": "boosh" });
@@ -0,0 +1 @@
1
+ reqwest_2({ "boosh": "boosh" });
@@ -0,0 +1 @@
1
+ ])}while(1);</x>{ "boosh": "boosh" }
@@ -0,0 +1,5 @@
1
+ this is not valid JSON!, there: are ~!_+ punctuation
2
+
3
+ marks
4
+
5
+ all, over, the:place ^ 2
@@ -0,0 +1,105 @@
1
+ <!DOCTYPE HTML>
2
+ <html lang="en-us">
3
+ <head>
4
+ <title>Reqwest tests</title>
5
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8">
6
+ <link rel="stylesheet" href="/node_modules/sink-test/src/sink.css" type="text/css">
7
+ <script src="/node_modules/valentine/valentine.js"></script>
8
+ <script src="/node_modules/sink-test/src/sink.js"></script>
9
+ <script src="/tests/ender.js"></script>
10
+ <script src="/src/reqwest.js"></script>
11
+ <script src="/src/ender.js"></script>
12
+ <style type="text/css">
13
+ #fixtures {
14
+ position: absolute;
15
+ top: -9999em;
16
+ }
17
+ </style>
18
+ </head>
19
+ <body>
20
+ <h1>Reqwest Tests</h1>
21
+ <div id="fixtures">
22
+ <form action="/foo" method="post">
23
+ <input type="submit" value="Continue">
24
+ <input type="text" name="foo" value="bar">
25
+ <input type="hidden" name="bar" value="baz">
26
+ <input type="checkbox" name="wha" checked value="1">
27
+ <input type="checkbox" name="wha" value="2">
28
+ <input type="checkbox" name="wha" checked value="3">
29
+ <input type="radio" name="who" value="one">
30
+ <input type="radio" name="who" checked value="tawoo">
31
+ <input type="radio" name="who" value="three">
32
+ <input type="text" name="$escapable name$" value="escapeme" />
33
+ <select name="choices">
34
+ <option>one</option>
35
+ <option selected>two</option>
36
+ <option>tres</option>
37
+ </select>
38
+ <textarea name="opinions">world peace is not real</textarea>
39
+ </form>
40
+ <form action="/baa" method="get">
41
+ <textarea name="T3" rows="2" cols="15">?
42
+ A B
43
+ Z</textarea>
44
+ <input type="hidden" name="H1" value="x" /> <!-- 0 -->
45
+ <input type="hidden" name="H2" /> <!-- 1 -->
46
+ <input type="password" name="PWD1" value="xyz" /> <!-- 2 -->
47
+ <input type="password" name="PWD2" /> <!-- 3 -->
48
+ <input type="text" name="T1" /> <!-- 4 -->
49
+ <input type="text" name="T2" value="YES" readonly="readonly" /> <!-- 5 -->
50
+ <input type="checkbox" name="C1" value="1" /> <!-- 6 -->
51
+ <input type="checkbox" name="C2" /> <!-- 7 -->
52
+ <input type="radio" name="R1" value="1" /> <!-- 8 -->
53
+ <input type="radio" name="R1" value="" /> <!-- 9 -->
54
+ <input type="text" name="My Name" value="me" /> <!-- 10 -->
55
+ <input type="reset" name="rst" value="NO" /> <!-- 11 -->
56
+ <input type="file" name="file" /> <!-- 12 -->
57
+ <input type="submit" name="sub" value="NO" /> <!-- 13 -->
58
+ <select name="S1"></select> <!-- 0 -->
59
+ <select name="S2"> <!-- 1 -->
60
+ <option value="abc">ABC</option>
61
+ <option value="def">DEF</option>
62
+ <option value="ghi">GHI</option>
63
+ <option value="jkl">JKL</option>
64
+ <option value="mno">MNO</option>
65
+ <option value="pqr">PQR</option>
66
+ <option value="disco stu">DISCO STU!</option>
67
+ <option value="vwx">VWX</option>
68
+ <option value="yz">YZ</option>
69
+ <option value="">no no no!</option>
70
+ </select>
71
+ <select name="S3"> <!-- 2 -->
72
+ <option>ABC</option>
73
+ <option>DEF</option>
74
+ <option>GHI</option>
75
+ <option>JKL</option>
76
+ <option>MNO</option>
77
+ <option>PQR</option>
78
+ <option>DISCO STU!</option>
79
+ <option>VWX</option>
80
+ <option>YZ</option>
81
+ </select>
82
+ <select name="S4" multiple="multiple" size="3"> <!-- 3 -->
83
+ <option value="1">One</option>
84
+ <option value="2">Two</option>
85
+ <option value="3">Three</option>
86
+ <option value="4">Four</option>
87
+ <option value="5">Five</option>
88
+ <option value="6">Six</option>
89
+ <option>Seven</option>
90
+ <option>Eight</option>
91
+ <option>Disco Stu!</option>
92
+ </select>
93
+ <input type="text" name="D1" value="NO" disabled="disabled" /> <!-- 14 -->
94
+ <input type="checkbox" name="D2" value="NO" checked="checked" disabled="disabled" /> <!-- 15 -->
95
+ <input type="radio" name="D3" value="NO" checked="checked" disabled="disabled" /> <!-- 16 -->
96
+ <select name="D4" disabled="disabled"><option selected="selected" value="NO">NO</option></select> <!-- 4 -->
97
+ <select name="D5"><option selected="selected" value="NO" disabled="disabled">NO</option></select> <!-- 5 -->
98
+ <select name="D4" disabled="disabled "multiple="multiple" size="3"><option selected="selected" value="NO">NO</option></select> <!-- 6 -->
99
+ <select name="D5" multiple="multiple" size="3"><option selected="selected" value="NO" disabled="disabled">NO</option></select> <!-- 7 -->
100
+ </form>
101
+ </div>
102
+ <ol id="tests"></ol>
103
+ <script src="/tests/tests.js"></script>
104
+ </body>
105
+ </html>
@@ -0,0 +1,1723 @@
1
+ /*jshint maxlen:80*/
2
+ /*global reqwest:true, sink:true, start:true, ender:true, v:true, boosh:true*/
3
+
4
+ (function (ajax) {
5
+ var BIND_ARGS = 'bind'
6
+ , PASS_ARGS = 'pass'
7
+ , FakeXHR = (function () {
8
+ function FakeXHR () {
9
+ this.args = {}
10
+ FakeXHR.last = this
11
+ }
12
+ FakeXHR.setup = function () {
13
+ FakeXHR.oldxhr = window['XMLHttpRequest']
14
+ FakeXHR.oldaxo = window['ActiveXObject']
15
+ window['XMLHttpRequest'] = FakeXHR
16
+ window['ActiveXObject'] = FakeXHR
17
+ FakeXHR.last = null
18
+ }
19
+ FakeXHR.restore = function () {
20
+ window['XMLHttpRequest'] = FakeXHR.oldxhr
21
+ window['ActiveXObject'] = FakeXHR.oldaxo
22
+ }
23
+ FakeXHR.prototype.methodCallCount = function (name) {
24
+ return this.args[name] ? this.args[name].length : 0
25
+ }
26
+ FakeXHR.prototype.methodCallArgs = function (name, i, j) {
27
+ var a = this.args[name]
28
+ && this.args[name].length > i ? this.args[name][i] : null
29
+ if (arguments.length > 2) return a && a.length > j ? a[j] : null
30
+ return a
31
+ }
32
+ v.each(['open', 'send', 'setRequestHeader' ], function (f) {
33
+ FakeXHR.prototype[f] = function () {
34
+ if (!this.args[f]) this.args[f] = []
35
+ this.args[f].push(arguments)
36
+ }
37
+ })
38
+ return FakeXHR
39
+ }())
40
+
41
+ sink('Setup', function (test, ok, before, after) {
42
+ before(function () {
43
+ ajax.ajaxSetup({
44
+ dataFilter: function (resp, type) {
45
+ // example filter to prevent json hijacking
46
+ return resp.substring('])}while(1);</x>'.length)
47
+ }
48
+ })
49
+ })
50
+ after(function () {
51
+ ajax.ajaxSetup({
52
+ // reset to original data filter
53
+ dataFilter: function (resp, type) {
54
+ return resp
55
+ }
56
+ })
57
+ })
58
+ test('dataFilter', function (complete) {
59
+ ajax({
60
+ url: '/tests/fixtures/fixtures_with_prefix.json'
61
+ , type: 'json'
62
+ , success: function (resp) {
63
+ ok(resp, 'received response')
64
+ ok(
65
+ resp && resp.boosh == 'boosh'
66
+ , 'correctly evaluated response as JSON'
67
+ )
68
+ complete()
69
+ }
70
+ })
71
+ })
72
+ })
73
+
74
+ sink('Mime Types', function (test, ok) {
75
+ test('JSON', function (complete) {
76
+ ajax({
77
+ url: '/tests/fixtures/fixtures.json'
78
+ , type: 'json'
79
+ , success: function (resp) {
80
+ ok(resp, 'received response')
81
+ ok(
82
+ resp && resp.boosh == 'boosh'
83
+ , 'correctly evaluated response as JSON'
84
+ )
85
+ complete()
86
+ }
87
+ })
88
+ })
89
+
90
+ test('JSONP', function (complete) {
91
+ // stub callback prefix
92
+ reqwest.getcallbackPrefix = function (id) {
93
+ return 'reqwest_' + id
94
+ }
95
+ ajax({
96
+ url: '/tests/fixtures/fixtures_jsonp.jsonp?callback=?'
97
+ , type: 'jsonp'
98
+ , success: function (resp) {
99
+ ok(resp, 'received response for unique generated callback')
100
+ ok(
101
+ resp && resp.boosh == 'boosh'
102
+ , 'correctly evaled response for unique generated cb as JSONP'
103
+ )
104
+ complete()
105
+ }
106
+ })
107
+ })
108
+
109
+ test('JS', function (complete) {
110
+ ajax({
111
+ url: '/tests/fixtures/fixtures.js'
112
+ , type: 'js'
113
+ , success: function () {
114
+ ok(
115
+ typeof boosh !== 'undefined' && boosh == 'boosh'
116
+ , 'evaluated response as JavaScript'
117
+ )
118
+ complete()
119
+ }
120
+ })
121
+ })
122
+
123
+ test('HTML', function (complete) {
124
+ ajax({
125
+ url: '/tests/fixtures/fixtures.html'
126
+ , type: 'html'
127
+ , success: function (resp) {
128
+ ok(resp == '<p>boosh</p>', 'evaluated response as HTML')
129
+ complete()
130
+ }
131
+ })
132
+ })
133
+
134
+ test('XML', function (complete) {
135
+ ajax({
136
+ url: '/tests/fixtures/fixtures.xml'
137
+ , type: 'xml'
138
+ , success: function (resp) {
139
+ ok(resp
140
+ && resp.documentElement
141
+ && resp.documentElement.nodeName == 'root'
142
+ , 'XML Response root is <root>'
143
+ )
144
+ ok(resp
145
+ && resp.documentElement
146
+ && resp.documentElement.hasChildNodes
147
+ && resp.documentElement.firstChild.nodeName == 'boosh'
148
+ && resp.documentElement.firstChild.firstChild.nodeValue
149
+ == 'boosh'
150
+ , 'Correct XML response'
151
+ )
152
+ complete()
153
+ }
154
+ , error: function (err) {
155
+ ok(false, err.responseText)
156
+ complete()
157
+ }
158
+ })
159
+ })
160
+
161
+ test('XML (404)', function (complete) {
162
+ ajax({
163
+ url:'/tests/fixtures/badfixtures.xml'
164
+ , type:'xml'
165
+ , success: function (resp) {
166
+ if (resp == null) {
167
+ ok(true, 'XML response is null')
168
+ complete()
169
+ } else {
170
+ ok(resp
171
+ && resp.documentElement
172
+ && resp.documentElement.firstChild
173
+ && (/error/i).test(resp.documentElement.firstChild.nodeValue)
174
+ , 'XML response reports parsing error'
175
+ )
176
+ complete()
177
+ }
178
+ }
179
+ , error: function () {
180
+ ok(true, 'No XML response (error())')
181
+ complete()
182
+ }
183
+ })
184
+ })
185
+ })
186
+
187
+ sink('JSONP', function (test, ok) {
188
+ test('Named callback in query string', function (complete) {
189
+ ajax({
190
+ url: '/tests/fixtures/fixtures_jsonp2.jsonp?foo=bar'
191
+ , type: 'jsonp'
192
+ , jsonpCallback: 'foo'
193
+ , success: function (resp) {
194
+ ok(resp, 'received response for custom callback')
195
+ ok(
196
+ resp && resp.boosh == 'boosh'
197
+ , 'correctly evaluated response as JSONP with custom callback'
198
+ )
199
+ complete()
200
+ }
201
+ })
202
+ })
203
+
204
+ test('Unnamed callback in query string', function (complete) {
205
+ ajax({
206
+ url: '/tests/fixtures/fixtures_jsonp3.jsonp?foo=?'
207
+ , type: 'jsonp'
208
+ , jsonpCallback: 'foo'
209
+ , success: function (resp) {
210
+ ok(resp, 'received response for custom wildcard callback')
211
+ ok(
212
+ resp && resp.boosh == 'boosh'
213
+ , 'correctly evaled response as JSONP with custom wildcard cb'
214
+ )
215
+ complete()
216
+ }
217
+ })
218
+ })
219
+
220
+ test('No callback, no query string', function (complete) {
221
+ ajax({
222
+ url: '/tests/fixtures/fixtures_jsonp3.jsonp'
223
+ , type: 'jsonp'
224
+ , jsonpCallback: 'foo'
225
+ , success: function (resp) {
226
+ ok(resp, 'received response for custom wildcard callback')
227
+ ok(
228
+ resp && resp.boosh == 'boosh'
229
+ , 'correctly evaled response as JSONP with custom cb not in url'
230
+ )
231
+ complete()
232
+ }
233
+ })
234
+ })
235
+
236
+ test('No callback in existing query string', function (complete) {
237
+ ajax({
238
+ url: '/tests/none.jsonp?echo&somevar=some+long+str+here'
239
+ , type: 'jsonp'
240
+ , jsonpCallbackName: 'yohoho'
241
+ , success: function (resp) {
242
+ ok(resp && resp.query, 'received response from echo callback')
243
+ ok(
244
+ resp && resp.query && resp.query.somevar == 'some long str here'
245
+ , 'correctly evaluated response as JSONP with echo callback'
246
+ )
247
+ complete()
248
+ }
249
+ })
250
+ })
251
+
252
+ test('Append data to existing query string', function (complete) {
253
+ ajax({
254
+ url: '/tests/none.jsonp?echo' // should append &somevar...
255
+ , type: 'jsonp'
256
+ , data: { somevar: 'some long str here', anothervar: 'yo ho ho!' }
257
+ , success: function (resp) {
258
+ ok(resp && resp.query, 'received response from echo callback')
259
+ ok(
260
+ resp && resp.query && resp.query.somevar == 'some long str here'
261
+ , 'correctly sent and received data object from JSONP echo (1)'
262
+ )
263
+ ok(
264
+ resp && resp.query && resp.query.anothervar == 'yo ho ho!'
265
+ , 'correctly sent and received data object from JSONP echo (2)'
266
+ )
267
+ complete()
268
+ }
269
+ })
270
+ })
271
+
272
+ test('Generate complete query string from data', function (complete) {
273
+ ajax({
274
+ url: '/tests/none.jsonp' // should append ?echo...etc.
275
+ , type: 'jsonp'
276
+ , data: [
277
+ { name: 'somevar', value: 'some long str here' }
278
+ , { name: 'anothervar', value: 'yo ho ho!' }
279
+ , { name: 'echo', value: true }
280
+ ]
281
+ , success: function (resp) {
282
+ ok(resp && resp.query, 'received response from echo callback')
283
+ ok(
284
+ resp && resp.query && resp.query.somevar == 'some long str here'
285
+ , 'correctly sent and received data array from JSONP echo (1)'
286
+ )
287
+ ok(
288
+ resp && resp.query && resp.query.anothervar == 'yo ho ho!'
289
+ , 'correctly sent and received data array from JSONP echo (2)'
290
+ )
291
+ complete()
292
+ }
293
+ })
294
+ })
295
+
296
+ test('Append data to query string and insert callback name'
297
+ , function (complete) {
298
+
299
+ ajax({
300
+ // should append data and match callback correctly
301
+ url: '/tests/none.jsonp?callback=?'
302
+ , type: 'jsonp'
303
+ , jsonpCallbackName: 'reqwest_foo'
304
+ , data: { foo: 'bar', boo: 'baz', echo: true }
305
+ , success: function (resp) {
306
+ ok(resp && resp.query, 'received response from echo callback')
307
+ ok(
308
+ resp && resp.query && resp.query.callback == 'reqwest_foo'
309
+ , 'correctly matched callback in URL'
310
+ )
311
+ complete()
312
+ }
313
+ })
314
+ })
315
+ })
316
+
317
+ sink('Callbacks', function (test, ok) {
318
+
319
+ test('sync version', function (done) {
320
+ var r = ajax({
321
+ method: 'get'
322
+ , url: '/tests/fixtures/fixtures.json'
323
+ , type: 'json'
324
+ , async: false
325
+ })
326
+ ok(eval('(' + r.request.response + ')').boosh == 'boosh', 'can make sync calls')
327
+ done()
328
+ })
329
+
330
+ test('no callbacks', function (complete) {
331
+ var pass = true
332
+ try {
333
+ ajax('/tests/fixtures/fixtures.js')
334
+ } catch (ex) {
335
+ pass = false
336
+ } finally {
337
+ ok(pass, 'successfully doesnt fail without callback')
338
+ complete()
339
+ }
340
+ })
341
+
342
+ test('complete is called', function (complete) {
343
+ ajax({
344
+ url: '/tests/fixtures/fixtures.js'
345
+ , complete: function () {
346
+ ok(true, 'called complete')
347
+ complete()
348
+ }
349
+ })
350
+ })
351
+
352
+ test('invalid JSON sets error on resp object', function (complete) {
353
+ ajax({
354
+ url: '/tests/fixtures/invalidJSON.json'
355
+ , type: 'json'
356
+ , success: function () {
357
+ ok(false, 'success callback fired')
358
+ complete()
359
+ }
360
+ , error: function (resp, msg) {
361
+ ok(
362
+ msg == 'Could not parse JSON in response'
363
+ , 'error callback fired'
364
+ )
365
+ complete()
366
+ }
367
+ })
368
+ })
369
+
370
+ test('multiple parallel named JSONP callbacks', 8, function () {
371
+ ajax({
372
+ url: '/tests/fixtures/fixtures_jsonp_multi.jsonp?callback=reqwest_0'
373
+ , type: 'jsonp'
374
+ , success: function (resp) {
375
+ ok(resp, 'received response from call #1')
376
+ ok(
377
+ resp && resp.a == 'a'
378
+ , 'evaluated response from call #1 as JSONP'
379
+ )
380
+ }
381
+ })
382
+ ajax({
383
+ url: '/tests/fixtures/fixtures_jsonp_multi_b.jsonp?callback=reqwest_0'
384
+ , type: 'jsonp'
385
+ , success: function (resp) {
386
+ ok(resp, 'received response from call #2')
387
+ ok(
388
+ resp && resp.b == 'b'
389
+ , 'evaluated response from call #2 as JSONP'
390
+ )
391
+ }
392
+ })
393
+ ajax({
394
+ url: '/tests/fixtures/fixtures_jsonp_multi_c.jsonp?callback=reqwest_0'
395
+ , type: 'jsonp'
396
+ , success: function (resp) {
397
+ ok(resp, 'received response from call #2')
398
+ ok(
399
+ resp && resp.c == 'c'
400
+ , 'evaluated response from call #3 as JSONP'
401
+ )
402
+ }
403
+ })
404
+ ajax({
405
+ url: '/tests/fixtures/fixtures_jsonp_multi.jsonp?callback=reqwest_0'
406
+ , type: 'jsonp'
407
+ , success: function (resp) {
408
+ ok(resp, 'received response from call #2')
409
+ ok(
410
+ resp && resp.a == 'a'
411
+ , 'evaluated response from call #4 as JSONP'
412
+ )
413
+ }
414
+ })
415
+ })
416
+
417
+ test('JSONP also supports success promises', function (complete) {
418
+ ajax({
419
+ url: '/tests/none.jsonp?echo'
420
+ , type: 'jsonp'
421
+ , success: function (resp) {
422
+ ok(resp, 'received response in constructor success callback')
423
+ }
424
+ })
425
+ .then(function (resp) {
426
+ ok(resp, 'received response in promise success callback')
427
+ })
428
+ .then(function (resp) {
429
+ ok(resp, 'received response in second promise success callback')
430
+ complete()
431
+ })
432
+ })
433
+
434
+ test('JSONP also supports error promises', function (complete) {
435
+ ajax({
436
+ url: '/tests/timeout/'
437
+ , type: 'jsonp'
438
+ , error: function (err) {
439
+ ok(err, 'received error response in constructor error callback')
440
+ }
441
+ })
442
+ .fail(function (err) {
443
+ ok(err, 'received error response in promise error callback')
444
+ })
445
+ .fail(function (err) {
446
+ ok(err, 'received error response in second promise error callback')
447
+ complete()
448
+ })
449
+ .abort()
450
+ })
451
+
452
+ })
453
+
454
+ if (window.XMLHttpRequest
455
+ && ('withCredentials' in new window.XMLHttpRequest())) {
456
+
457
+ sink('Cross-origin Resource Sharing', function (test, ok) {
458
+ test('make request to another origin', 1, function () {
459
+ ajax({
460
+ url: 'http://' + window.location.hostname + ':5678/get-value'
461
+ , type: 'text'
462
+ , method: 'get'
463
+ , crossOrigin: true
464
+ , complete: function (resp) {
465
+ ok(resp.responseText === 'hello', 'request made successfully')
466
+ }
467
+ })
468
+ })
469
+
470
+ test('set cookie on other origin', 2, function () {
471
+ ajax({
472
+ url: 'http://' + window.location.hostname + ':5678/set-cookie'
473
+ , type: 'text'
474
+ , method: 'get'
475
+ , crossOrigin: true
476
+ , withCredentials: true
477
+ , before: function (http) {
478
+ ok(
479
+ http.withCredentials === true
480
+ , 'has set withCredentials on connection object'
481
+ )
482
+ }
483
+ , complete: function (resp) {
484
+ ok(resp.status === 200, 'cookie set successfully')
485
+ }
486
+ })
487
+ })
488
+
489
+ test('get cookie from other origin', 1, function () {
490
+ ajax({
491
+ url: 'http://'
492
+ + window.location.hostname
493
+ + ':5678/get-cookie-value'
494
+ , type: 'text'
495
+ , method: 'get'
496
+ , crossOrigin: true
497
+ , withCredentials: true
498
+ , complete: function (resp) {
499
+ ok(
500
+ resp.responseText == 'hello'
501
+ , 'cookie value retrieved successfully'
502
+ )
503
+ }
504
+ })
505
+ })
506
+
507
+ })
508
+ }
509
+
510
+ sink('Connection Object', function (test, ok) {
511
+
512
+ test('setRequestHeaders', function (complete) {
513
+ ajax({
514
+ url: '/tests/fixtures/fixtures.html'
515
+ , data: 'foo=bar&baz=thunk'
516
+ , method: 'post'
517
+ , headers: {
518
+ 'Accept': 'application/x-foo'
519
+ }
520
+ , success: function () {
521
+ ok(true, 'can post headers')
522
+ complete()
523
+ }
524
+ })
525
+ })
526
+
527
+ test('can inspect http before send', function (complete) {
528
+ var connection = ajax({
529
+ url: '/tests/fixtures/fixtures.js'
530
+ , method: 'post'
531
+ , type: 'js'
532
+ , before: function (http) {
533
+ ok(http.readyState == 1, 'received http connection object')
534
+ }
535
+ , success: function () {
536
+ // Microsoft.XMLHTTP appears not to run this async in IE6&7, it
537
+ // processes the request and triggers success() before ajax() even
538
+ // returns. Perhaps a better solution would be to defer the calls
539
+ // within handleReadyState()
540
+ setTimeout(function () {
541
+ ok(
542
+ connection.request.readyState == 4
543
+ , 'success callback has readyState of 4'
544
+ )
545
+ complete()
546
+ }, 0)
547
+ }
548
+ })
549
+ })
550
+
551
+ test('ajax() encodes array `data`', function (complete) {
552
+ FakeXHR.setup()
553
+ try {
554
+ ajax({
555
+ url: '/tests/fixtures/fixtures.html'
556
+ , method: 'post'
557
+ , data: [
558
+ { name: 'foo', value: 'bar' }
559
+ , { name: 'baz', value: 'thunk' }
560
+ ]
561
+ })
562
+ ok(FakeXHR.last.methodCallCount('send') == 1, 'send called')
563
+ ok(
564
+ FakeXHR.last.methodCallArgs('send', 0).length == 1
565
+ , 'send called with 1 arg'
566
+ )
567
+ ok(
568
+ FakeXHR.last.methodCallArgs('send', 0, 0) == 'foo=bar&baz=thunk'
569
+ , 'send called with encoded array'
570
+ )
571
+ complete()
572
+ } finally {
573
+ FakeXHR.restore()
574
+ }
575
+ })
576
+
577
+ test('ajax() encodes hash `data`', function (complete) {
578
+ FakeXHR.setup()
579
+ try {
580
+ ajax({
581
+ url: '/tests/fixtures/fixtures.html'
582
+ , method: 'post'
583
+ , data: { bar: 'foo', thunk: 'baz' }
584
+ })
585
+ ok(FakeXHR.last.methodCallCount('send') == 1, 'send called')
586
+ ok(
587
+ FakeXHR.last.methodCallArgs('send', 0).length == 1
588
+ , 'send called with 1 arg'
589
+ )
590
+ ok(
591
+ FakeXHR.last.methodCallArgs('send', 0, 0) == 'bar=foo&thunk=baz'
592
+ , 'send called with encoded array'
593
+ )
594
+ complete()
595
+ } finally {
596
+ FakeXHR.restore()
597
+ }
598
+ })
599
+
600
+ test('ajax() obeys `processData`', function (complete) {
601
+ FakeXHR.setup()
602
+ try {
603
+ var d = { bar: 'foo', thunk: 'baz' }
604
+ ajax({
605
+ url: '/tests/fixtures/fixtures.html'
606
+ , processData: false
607
+ , method: 'post'
608
+ , data: d
609
+ })
610
+ ok(FakeXHR.last.methodCallCount('send') == 1, 'send called')
611
+ ok(
612
+ FakeXHR.last.methodCallArgs('send', 0).length == 1
613
+ , 'send called with 1 arg'
614
+ )
615
+ ok(
616
+ FakeXHR.last.methodCallArgs('send', 0, 0) === d
617
+ , 'send called with exact `data` object'
618
+ )
619
+ complete()
620
+ } finally {
621
+ FakeXHR.restore()
622
+ }
623
+ })
624
+
625
+ function testXhrGetUrlAdjustment(url, data, expectedUrl, complete) {
626
+ FakeXHR.setup()
627
+ try {
628
+ ajax({ url: url, data: data })
629
+ ok(FakeXHR.last.methodCallCount('open') == 1, 'open called')
630
+ ok(
631
+ FakeXHR.last.methodCallArgs('open', 0).length == 3
632
+ , 'open called with 3 args'
633
+ )
634
+ ok(
635
+ FakeXHR.last.methodCallArgs('open', 0, 0) == 'GET'
636
+ , 'first arg of open() is "GET"'
637
+ )
638
+ ok(FakeXHR.last.methodCallArgs('open', 0, 1) == expectedUrl
639
+ , 'second arg of open() is URL with query string')
640
+ ok(
641
+ FakeXHR.last.methodCallArgs('open', 0, 2) === true
642
+ , 'third arg of open() is `true`'
643
+ )
644
+ ok(FakeXHR.last.methodCallCount('send') == 1, 'send called')
645
+ ok(
646
+ FakeXHR.last.methodCallArgs('send', 0).length == 1
647
+ , 'send called with 1 arg'
648
+ )
649
+ ok(
650
+ FakeXHR.last.methodCallArgs('send', 0, 0) === null
651
+ , 'send called with null'
652
+ )
653
+ complete()
654
+ } finally {
655
+ FakeXHR.restore()
656
+ }
657
+ }
658
+
659
+ test('ajax() appends GET URL with ?`data`', function (complete) {
660
+ testXhrGetUrlAdjustment(
661
+ '/tests/fixtures/fixtures.html'
662
+ , 'bar=foo&thunk=baz'
663
+ , '/tests/fixtures/fixtures.html?bar=foo&thunk=baz'
664
+ , complete
665
+ )
666
+ })
667
+
668
+ test('ajax() appends GET URL with ?`data` (serialized object)'
669
+ , function (complete) {
670
+
671
+ testXhrGetUrlAdjustment(
672
+ '/tests/fixtures/fixtures.html'
673
+ , { bar: 'foo', thunk: 'baz' }
674
+ , '/tests/fixtures/fixtures.html?bar=foo&thunk=baz'
675
+ , complete
676
+ )
677
+ })
678
+
679
+ test('ajax() appends GET URL with &`data` (serialized array)'
680
+ , function (complete) {
681
+
682
+ testXhrGetUrlAdjustment(
683
+ '/tests/fixtures/fixtures.html?x=y'
684
+ , [ { name: 'bar', value: 'foo'}, {name: 'thunk', value: 'baz' } ]
685
+ , '/tests/fixtures/fixtures.html?x=y&bar=foo&thunk=baz'
686
+ , complete
687
+ )
688
+ })
689
+ })
690
+
691
+ sink('Standard vs compat mode', function (test, ok) {
692
+ function methodMatch(resp, method) {
693
+ return resp && resp.method === method
694
+ }
695
+ function headerMatch(resp, key, expected) {
696
+ return resp && resp.headers && resp.headers[key] === expected
697
+ }
698
+ function queryMatch(resp, key, expected) {
699
+ return resp && resp.query && resp.query[key] === expected
700
+ }
701
+
702
+ test('standard mode default', function (complete) {
703
+ ajax({
704
+ url: '/tests/none.json?echo'
705
+ , success: function (resp) {
706
+ ok(methodMatch(resp, 'GET'), 'correct request method (GET)')
707
+ ok(
708
+ headerMatch(
709
+ resp
710
+ , 'content-type'
711
+ , 'application/x-www-form-urlencoded'
712
+ )
713
+ , 'correct Content-Type request header'
714
+ )
715
+ ok(
716
+ headerMatch(resp, 'x-requested-with', 'XMLHttpRequest')
717
+ , 'correct X-Requested-With header'
718
+ )
719
+ ok(
720
+ headerMatch(
721
+ resp
722
+ , 'accept'
723
+ , 'text/javascript, text/html, application/xml, text/xml, */*'
724
+ )
725
+ , 'correct Accept header'
726
+ )
727
+ complete()
728
+ }
729
+ })
730
+ })
731
+
732
+ test('standard mode custom content-type', function (complete) {
733
+ ajax({
734
+ url: '/tests/none.json?echo'
735
+ , contentType: 'yapplication/foobar'
736
+ , success: function (resp) {
737
+ ok(methodMatch(resp, 'GET'), 'correct request method (GET)')
738
+ ok(
739
+ headerMatch(resp, 'content-type', 'yapplication/foobar')
740
+ , 'correct Content-Type request header'
741
+ )
742
+ ok(
743
+ headerMatch(resp, 'x-requested-with', 'XMLHttpRequest')
744
+ , 'correct X-Requested-With header'
745
+ )
746
+ ok(
747
+ headerMatch(
748
+ resp
749
+ , 'accept'
750
+ , 'text/javascript, text/html, application/xml, text/xml, */*'
751
+ )
752
+ , 'correct Accept header'
753
+ )
754
+ complete()
755
+ }
756
+ })
757
+ })
758
+
759
+ test('compat mode "dataType=json" headers', function (complete) {
760
+ ajax.compat({
761
+ url: '/tests/none.json?echo'
762
+ , dataType: 'json' // should map to 'type'
763
+ , success: function (resp) {
764
+ ok(methodMatch(resp, 'GET'), 'correct request method (GET)')
765
+ ok(
766
+ headerMatch(
767
+ resp
768
+ , 'content-type'
769
+ , 'application/x-www-form-urlencoded'
770
+ )
771
+ , 'correct Content-Type request header'
772
+ )
773
+ ok(
774
+ headerMatch(resp, 'x-requested-with', 'XMLHttpRequest')
775
+ , 'correct X-Requested-With header'
776
+ )
777
+ ok(
778
+ headerMatch(resp, 'accept', 'application/json, text/javascript')
779
+ , 'correct Accept header'
780
+ )
781
+ complete()
782
+ }
783
+ })
784
+ })
785
+
786
+ test('compat mode "dataType=json" with "type=post" headers'
787
+ , function (complete) {
788
+ ajax.compat({
789
+ url: '/tests/none.json?echo'
790
+ , type: 'post'
791
+ , dataType: 'json' // should map to 'type'
792
+ , success: function (resp) {
793
+ ok(methodMatch(resp, 'POST'), 'correct request method (POST)')
794
+ ok(
795
+ headerMatch(
796
+ resp
797
+ , 'content-type'
798
+ , 'application/x-www-form-urlencoded'
799
+ )
800
+ , 'correct Content-Type request header'
801
+ )
802
+ ok(
803
+ headerMatch(resp, 'x-requested-with', 'XMLHttpRequest')
804
+ , 'correct X-Requested-With header'
805
+ )
806
+ ok(
807
+ headerMatch(resp, 'accept', 'application/json, text/javascript')
808
+ , 'correct Accept header'
809
+ )
810
+ complete()
811
+ }
812
+ })
813
+ })
814
+
815
+ test('compat mode "dataType=json" headers (with additional headers)'
816
+ , function (complete) {
817
+
818
+ ajax.compat({
819
+ url: '/tests/none.json?echo'
820
+ , dataType: 'json' // should map to 'type'
821
+ // verify that these are left intact and nothing screwy
822
+ // happens with headers
823
+ , headers: { one: 1, two: 2 }
824
+ , success: function (resp) {
825
+ ok(
826
+ headerMatch(
827
+ resp
828
+ , 'content-type'
829
+ , 'application/x-www-form-urlencoded'
830
+ )
831
+ , 'correct Content-Type request header'
832
+ )
833
+ ok(
834
+ headerMatch(resp, 'x-requested-with', 'XMLHttpRequest')
835
+ , 'correct X-Requested-With header'
836
+ )
837
+ ok(
838
+ headerMatch(resp, 'accept', 'application/json, text/javascript')
839
+ , 'correct Accept header'
840
+ )
841
+ ok(
842
+ headerMatch(resp, 'one', '1') && headerMatch(resp, 'two', '2')
843
+ , 'left additional headers intact'
844
+ )
845
+ complete()
846
+ }
847
+ })
848
+ })
849
+
850
+ test('compat mode "dataType=jsonp" query string', function (complete) {
851
+ ajax.compat({
852
+ url: '/tests/none.jsonp?echo'
853
+ , dataType: 'jsonp'
854
+ , jsonp: 'testCallback' // should map to jsonpCallback
855
+ , jsonpCallback: 'foobar' // should map to jsonpCallbackName
856
+ , success: function (resp) {
857
+ ok(
858
+ queryMatch(resp, 'echo', '')
859
+ , 'correct Content-Type request header'
860
+ )
861
+ ok(
862
+ queryMatch(resp, 'testCallback', 'foobar')
863
+ , 'correct X-Requested-With header'
864
+ )
865
+ complete()
866
+ }
867
+ })
868
+ })
869
+ })
870
+
871
+ /***************** SERIALIZER TESTS ***********************/
872
+
873
+ // define some helpers for the serializer tests that are used often and
874
+ // shared with the ender integration tests
875
+
876
+ function createSerializeHelper(ok) {
877
+ var forms = document.forms
878
+ , foo = forms[0].getElementsByTagName('input')[1]
879
+ , bar = forms[0].getElementsByTagName('input')[2]
880
+ , choices = forms[0].getElementsByTagName('select')[0]
881
+ , BIND_ARGS = 'bind'
882
+ , PASS_ARGS = 'pass'
883
+
884
+ function reset() {
885
+ forms[1].reset()
886
+ }
887
+
888
+ function formElements(formIndex, tagName, elementIndex) {
889
+ return forms[formIndex].getElementsByTagName(tagName)[elementIndex]
890
+ }
891
+
892
+ function isArray(a) {
893
+ return Object.prototype.toString.call(a) == '[object Array]'
894
+ }
895
+
896
+ function sameValue(value, expected) {
897
+ if (expected == null) {
898
+ return value === null
899
+ } else if (isArray(expected)) {
900
+ if (value.length !== expected.length) return false
901
+ for (var i = 0; i < expected.length; i++) {
902
+ if (value[i] != expected[i]) return false
903
+ }
904
+ return true
905
+ } else return value == expected
906
+ }
907
+
908
+ function testInput(input, name, value, str) {
909
+ var sa = ajax.serialize(input, { type: 'array' })
910
+ , sh = ajax.serialize(input, { type: 'map' })
911
+ , av, i
912
+
913
+ if (value != null) {
914
+ av = isArray(value) ? value : [ value ]
915
+
916
+ ok(
917
+ sa.length == av.length
918
+ , 'serialize(' + str + ', {type:\'array\'}) returns array '
919
+ + '[{name,value}]'
920
+ )
921
+
922
+ for (i = 0; i < av.length; i++) {
923
+ ok(
924
+ name == sa[i].name
925
+ , 'serialize(' + str + ', {type:\'array\'})[' + i + '].name'
926
+ )
927
+ ok(
928
+ av[i] == sa[i].value
929
+ , 'serialize(' + str + ', {type:\'array\'})[' + i + '].value'
930
+ )
931
+ }
932
+
933
+ ok(sameValue(sh[name], value), 'serialize(' + str + ', {type:\'map\'})')
934
+ } else {
935
+ // the cases where an element shouldn't show up at all, checkbox not
936
+ // checked for example
937
+ ok(sa.length === 0, 'serialize(' + str + ', {type:\'array\'}) is []')
938
+ ok(
939
+ v.keys(sh).length === 0
940
+ , 'serialize(' + str + ', {type:\'map\'}) is {}'
941
+ )
942
+ }
943
+ }
944
+
945
+ function testFormSerialize(method, type) {
946
+ var expected =
947
+ 'foo=bar&bar=baz&wha=1&wha=3&who=tawoo&%24escapable+name'
948
+ + '%24=escapeme&choices=two&opinions=world+peace+is+not+real'
949
+
950
+ ok(method, 'serialize() bound to context')
951
+ ok(
952
+ (method ? method(forms[0]) : null) == expected
953
+ , 'serialized form (' + type + ')'
954
+ )
955
+ }
956
+
957
+ function executeMultiArgumentMethod(method, argType, options) {
958
+ var els = [ foo, bar, choices ]
959
+ , ths = argType === BIND_ARGS ? ender(els) : null
960
+ , args = argType === PASS_ARGS ? els : []
961
+
962
+ if (!!options) args.push(options)
963
+
964
+ return method.apply(ths, args)
965
+ }
966
+
967
+ function testMultiArgumentSerialize(method, type, argType) {
968
+ ok(method, 'serialize() bound in context')
969
+ var result = method ? executeMultiArgumentMethod(method, argType) : null
970
+ ok(
971
+ result == 'foo=bar&bar=baz&choices=two'
972
+ , 'serialized all 3 arguments together'
973
+ )
974
+ }
975
+
976
+ function verifyFormSerializeArray(result, type) {
977
+ var expected = [
978
+ { name: 'foo', value: 'bar' }
979
+ , { name: 'bar', value: 'baz' }
980
+ , { name: 'wha', value: 1 }
981
+ , { name: 'wha', value: 3 }
982
+ , { name: 'who', value: 'tawoo' }
983
+ , { name: '$escapable name$', value: 'escapeme' }
984
+ , { name: 'choices', value: 'two' }
985
+ , { name: 'opinions', value: 'world peace is not real' }
986
+ ]
987
+ , i
988
+
989
+ for (i = 0; i < expected.length; i++) {
990
+ ok(v.some(result, function (v) {
991
+ return v.name == expected[i].name && v.value == expected[i].value
992
+ }), 'serialized ' + expected[i].name + ' (' + type + ')')
993
+ }
994
+ }
995
+
996
+ function testFormSerializeArray(method, type) {
997
+ ok(method, 'serialize(..., {type:\'array\'}) bound to context')
998
+
999
+ var result = method ? method(forms[0], { type: 'array' }) : []
1000
+ if (!result) result = []
1001
+
1002
+ verifyFormSerializeArray(result, type)
1003
+ }
1004
+
1005
+ function testMultiArgumentSerializeArray(method, type, argType) {
1006
+ ok(method, 'serialize(..., {type:\'array\'}) bound to context')
1007
+ var result = method
1008
+ ? executeMultiArgumentMethod(method, argType, { type: 'array' })
1009
+ : []
1010
+
1011
+ if (!result) result = []
1012
+
1013
+ ok(result.length == 3, 'serialized as array of 3')
1014
+ ok(
1015
+ result.length == 3
1016
+ && result[0].name == 'foo'
1017
+ && result[0].value == 'bar'
1018
+ , 'serialized first element (' + type + ')'
1019
+ )
1020
+ ok(
1021
+ result.length == 3
1022
+ && result[1].name == 'bar'
1023
+ && result[1].value == 'baz'
1024
+ , 'serialized second element (' + type + ')'
1025
+ )
1026
+ ok(
1027
+ result.length == 3
1028
+ && result[2].name == 'choices'
1029
+ && result[2].value == 'two'
1030
+ , 'serialized third element (' + type + ')'
1031
+ )
1032
+ }
1033
+
1034
+ function testFormSerializeHash(method, type) {
1035
+ var expected = {
1036
+ foo: 'bar'
1037
+ , bar: 'baz'
1038
+ , wha: [ '1', '3' ]
1039
+ , who: 'tawoo'
1040
+ , '$escapable name$': 'escapeme'
1041
+ , choices: 'two'
1042
+ , opinions: 'world peace is not real'
1043
+ }
1044
+ , result
1045
+
1046
+ ok(method, 'serialize({type:\'map\'}) bound to context')
1047
+
1048
+ result = method ? method(forms[0], { type: 'map' }) : {}
1049
+ if (!result) result = {}
1050
+
1051
+ ok(
1052
+ v.keys(expected).length === v.keys(result).length
1053
+ , 'same number of keys (' + type + ')'
1054
+ )
1055
+
1056
+ v.each(v.keys(expected), function (k) {
1057
+ ok(
1058
+ sameValue(expected[k], result[k])
1059
+ , 'same value for ' + k + ' (' + type + ')'
1060
+ )
1061
+ })
1062
+ }
1063
+
1064
+ function testMultiArgumentSerializeHash(method, type, argType) {
1065
+ ok(method, 'serialize({type:\'map\'}) bound to context')
1066
+ var result = method
1067
+ ? executeMultiArgumentMethod(method, argType, { type: 'map' })
1068
+ : {}
1069
+ if (!result) result = {}
1070
+ ok(result.foo == 'bar', 'serialized first element (' + type + ')')
1071
+ ok(result.bar == 'baz', 'serialized second element (' + type + ')')
1072
+ ok(result.choices == 'two', 'serialized third element (' + type + ')')
1073
+ }
1074
+
1075
+ return {
1076
+ reset: reset
1077
+ , formElements: formElements
1078
+ , testInput: testInput
1079
+ , testFormSerialize: testFormSerialize
1080
+ , testMultiArgumentSerialize: testMultiArgumentSerialize
1081
+ , testFormSerializeArray: testFormSerializeArray
1082
+ , verifyFormSerializeArray: verifyFormSerializeArray
1083
+ , testMultiArgumentSerializeArray: testMultiArgumentSerializeArray
1084
+ , testFormSerializeHash: testFormSerializeHash
1085
+ , testMultiArgumentSerializeHash: testMultiArgumentSerializeHash
1086
+ }
1087
+ }
1088
+
1089
+ sink('Serializing', function (test, ok) {
1090
+
1091
+ /*
1092
+ * Serialize forms according to spec.
1093
+ * * reqwest.serialize(ele[, ele...]) returns a query string style
1094
+ * serialization
1095
+ * * reqwest.serialize(ele[, ele...], {type:'array'}) returns a
1096
+ * [ { name: 'name', value: 'value'}, ... ] style serialization,
1097
+ * compatible with jQuery.serializeArray()
1098
+ * * reqwest.serialize(ele[, ele...], {type:\'map\'}) returns a
1099
+ * { 'name': 'value', ... } style serialization, compatible with
1100
+ * Prototype Form.serializeElements({hash:true})
1101
+ * Some tests based on spec notes here:
1102
+ * http://malsup.com/jquery/form/comp/test.html
1103
+ */
1104
+
1105
+ var sHelper = createSerializeHelper(ok)
1106
+ sHelper.reset()
1107
+
1108
+ test('correctly serialize textarea', function (complete) {
1109
+ var textarea = sHelper.formElements(1, 'textarea', 0)
1110
+ , sa
1111
+
1112
+ // the texarea has 2 different newline styles, should come out as
1113
+ // normalized CRLF as per forms spec
1114
+ ok(
1115
+ 'T3=%3F%0D%0AA+B%0D%0AZ' == ajax.serialize(textarea)
1116
+ , 'serialize(textarea)'
1117
+ )
1118
+ sa = ajax.serialize(textarea, { type: 'array' })
1119
+ ok(sa.length == 1, 'serialize(textarea, {type:\'array\'}) returns array')
1120
+ sa = sa[0]
1121
+ ok('T3' == sa.name, 'serialize(textarea, {type:\'array\'}).name')
1122
+ ok(
1123
+ '?\r\nA B\r\nZ' == sa.value
1124
+ , 'serialize(textarea, {type:\'array\'}).value'
1125
+ )
1126
+ ok(
1127
+ '?\r\nA B\r\nZ' == ajax.serialize(textarea, { type: 'map' }).T3
1128
+ , 'serialize(textarea, {type:\'map\'})'
1129
+ )
1130
+ complete()
1131
+ })
1132
+
1133
+ test('correctly serialize input[type=hidden]', function (complete) {
1134
+ sHelper.testInput(
1135
+ sHelper.formElements(1, 'input', 0)
1136
+ , 'H1'
1137
+ , 'x'
1138
+ , 'hidden'
1139
+ )
1140
+ sHelper.testInput(
1141
+ sHelper.formElements(1, 'input', 1)
1142
+ , 'H2'
1143
+ , ''
1144
+ , 'hidden[no value]'
1145
+ )
1146
+ complete()
1147
+ })
1148
+
1149
+ test('correctly serialize input[type=password]', function (complete) {
1150
+ sHelper.testInput(
1151
+ sHelper.formElements(1, 'input', 2)
1152
+ , 'PWD1'
1153
+ , 'xyz'
1154
+ , 'password'
1155
+ )
1156
+ sHelper.testInput(
1157
+ sHelper.formElements(1, 'input', 3)
1158
+ , 'PWD2'
1159
+ , ''
1160
+ , 'password[no value]'
1161
+ )
1162
+ complete()
1163
+ })
1164
+
1165
+ test('correctly serialize input[type=text]', function (complete) {
1166
+ sHelper.testInput(
1167
+ sHelper.formElements(1, 'input', 4)
1168
+ , 'T1'
1169
+ , ''
1170
+ , 'text[no value]'
1171
+ )
1172
+ sHelper.testInput(
1173
+ sHelper.formElements(1, 'input', 5)
1174
+ , 'T2'
1175
+ , 'YES'
1176
+ , 'text[readonly]'
1177
+ )
1178
+ sHelper.testInput(
1179
+ sHelper.formElements(1, 'input', 10)
1180
+ , 'My Name'
1181
+ , 'me'
1182
+ , 'text[space name]'
1183
+ )
1184
+ complete()
1185
+ })
1186
+
1187
+ test('correctly serialize input[type=checkbox]', function (complete) {
1188
+ var cb1 = sHelper.formElements(1, 'input', 6)
1189
+ , cb2 = sHelper.formElements(1, 'input', 7)
1190
+ sHelper.testInput(cb1, 'C1', null, 'checkbox[not checked]')
1191
+ cb1.checked = true
1192
+ sHelper.testInput(cb1, 'C1', '1', 'checkbox[checked]')
1193
+ // special case here, checkbox with no value='' should give you 'on'
1194
+ // for cb.value
1195
+ sHelper.testInput(cb2, 'C2', null, 'checkbox[no value, not checked]')
1196
+ cb2.checked = true
1197
+ sHelper.testInput(cb2, 'C2', 'on', 'checkbox[no value, checked]')
1198
+ complete()
1199
+ })
1200
+
1201
+ test('correctly serialize input[type=radio]', function (complete) {
1202
+ var r1 = sHelper.formElements(1, 'input', 8)
1203
+ , r2 = sHelper.formElements(1, 'input', 9)
1204
+ sHelper.testInput(r1, 'R1', null, 'radio[not checked]')
1205
+ r1.checked = true
1206
+ sHelper.testInput(r1, 'R1', '1', 'radio[not checked]')
1207
+ sHelper.testInput(r2, 'R1', null, 'radio[no value, not checked]')
1208
+ r2.checked = true
1209
+ sHelper.testInput(r2, 'R1', '', 'radio[no value, checked]')
1210
+ complete()
1211
+ })
1212
+
1213
+ test('correctly serialize input[type=reset]', function (complete) {
1214
+ sHelper.testInput(
1215
+ sHelper.formElements(1, 'input', 11)
1216
+ , 'rst'
1217
+ , null
1218
+ , 'reset'
1219
+ )
1220
+ complete()
1221
+ })
1222
+
1223
+ test('correctly serialize input[type=file]', function (complete) {
1224
+ sHelper.testInput(
1225
+ sHelper.formElements(1, 'input', 12)
1226
+ , 'file'
1227
+ , null
1228
+ , 'file'
1229
+ )
1230
+ complete()
1231
+ })
1232
+
1233
+ test('correctly serialize input[type=submit]', function (complete) {
1234
+ // we're only supposed to serialize a submit button if it was clicked to
1235
+ // perform this serialization:
1236
+ // http://www.w3.org/TR/html401/interact/forms.html#h-17.13.2
1237
+ // but we'll pretend to be oblivious to this part of the spec...
1238
+ sHelper.testInput(
1239
+ sHelper.formElements(1, 'input', 13)
1240
+ , 'sub'
1241
+ , 'NO'
1242
+ , 'submit'
1243
+ )
1244
+ complete()
1245
+ })
1246
+
1247
+ test('correctly serialize select with no options', function (complete) {
1248
+ var select = sHelper.formElements(1, 'select', 0)
1249
+ sHelper.testInput(select, 'S1', null, 'select, no options')
1250
+ complete()
1251
+ })
1252
+
1253
+ test('correctly serialize select with values', function (complete) {
1254
+ var select = sHelper.formElements(1, 'select', 1)
1255
+ sHelper.testInput(select, 'S2', 'abc', 'select option 1 (default)')
1256
+ select.selectedIndex = 1
1257
+ sHelper.testInput(select, 'S2', 'def', 'select option 2')
1258
+ select.selectedIndex = 6
1259
+ sHelper.testInput(select, 'S2', 'disco stu', 'select option 7')
1260
+ // a special case where we have <option value=''>X</option>, should
1261
+ // return '' rather than X which will happen if you just do a simple
1262
+ // `value=(option.value||option.text)`
1263
+ select.selectedIndex = 9
1264
+ sHelper.testInput(
1265
+ select
1266
+ , 'S2'
1267
+ , ''
1268
+ , 'select option 9, value="" should yield ""'
1269
+ )
1270
+ select.selectedIndex = -1
1271
+ sHelper.testInput(select, 'S2', null, 'select, unselected')
1272
+ complete()
1273
+ })
1274
+
1275
+ test('correctly serialize select without explicit values'
1276
+ , function (complete) {
1277
+
1278
+ var select = sHelper.formElements(1, 'select', 2)
1279
+ sHelper.testInput(select, 'S3', 'ABC', 'select option 1 (default)')
1280
+ select.selectedIndex = 1
1281
+ sHelper.testInput(select, 'S3', 'DEF', 'select option 2')
1282
+ select.selectedIndex = 6
1283
+ sHelper.testInput(select, 'S3', 'DISCO STU!', 'select option 7')
1284
+ select.selectedIndex = -1
1285
+ sHelper.testInput(select, 'S3', null, 'select, unselected')
1286
+ complete()
1287
+ })
1288
+
1289
+ test('correctly serialize select multiple', function (complete) {
1290
+ var select = sHelper.formElements(1, 'select', 3)
1291
+ sHelper.testInput(select, 'S4', null, 'select, unselected (default)')
1292
+ select.options[1].selected = true
1293
+ sHelper.testInput(select, 'S4', '2', 'select option 2')
1294
+ select.options[3].selected = true
1295
+ sHelper.testInput(select, 'S4', [ '2', '4' ], 'select options 2 & 4')
1296
+ select.options[8].selected = true
1297
+ sHelper.testInput(
1298
+ select
1299
+ , 'S4'
1300
+ , [ '2', '4', 'Disco Stu!' ]
1301
+ , 'select option 2 & 4 & 9'
1302
+ )
1303
+ select.options[3].selected = false
1304
+ sHelper.testInput(
1305
+ select
1306
+ , 'S4'
1307
+ , [ '2', 'Disco Stu!' ]
1308
+ , 'select option 2 & 9'
1309
+ )
1310
+ select.options[1].selected = false
1311
+ select.options[8].selected = false
1312
+ sHelper.testInput(select, 'S4', null, 'select, all unselected')
1313
+ complete()
1314
+ })
1315
+
1316
+ test('correctly serialize options', function (complete) {
1317
+ var option = sHelper.formElements(1, 'select', 1).options[6]
1318
+ sHelper.testInput(
1319
+ option
1320
+ , '-'
1321
+ , null
1322
+ , 'just option (with value), shouldn\'t serialize'
1323
+ )
1324
+
1325
+ option = sHelper.formElements(1, 'select', 2).options[6]
1326
+ sHelper.testInput(
1327
+ option
1328
+ , '-'
1329
+ , null
1330
+ , 'option (without value), shouldn\'t serialize'
1331
+ )
1332
+
1333
+ complete()
1334
+ })
1335
+
1336
+ test('correctly serialize disabled', function (complete) {
1337
+ var input = sHelper.formElements(1, 'input', 14)
1338
+ , select
1339
+
1340
+ sHelper.testInput(input, 'D1', null, 'disabled text input')
1341
+ input = sHelper.formElements(1, 'input', 15)
1342
+ sHelper.testInput(input, 'D2', null, 'disabled checkbox')
1343
+ input = sHelper.formElements(1, 'input', 16)
1344
+ sHelper.testInput(input, 'D3', null, 'disabled radio')
1345
+
1346
+ select = sHelper.formElements(1, 'select', 4)
1347
+ sHelper.testInput(select, 'D4', null, 'disabled select')
1348
+ select = sHelper.formElements(1, 'select', 3)
1349
+ sHelper.testInput(select, 'D5', null, 'disabled select option')
1350
+ select = sHelper.formElements(1, 'select', 6)
1351
+ sHelper.testInput(select, 'D6', null, 'disabled multi select')
1352
+ select = sHelper.formElements(1, 'select', 7)
1353
+ sHelper.testInput(select, 'D7', null, 'disabled multi select option')
1354
+ complete()
1355
+ })
1356
+
1357
+ test('serialize(form)', function (complete) {
1358
+ sHelper.testFormSerialize(ajax.serialize, 'direct')
1359
+ complete()
1360
+ })
1361
+
1362
+ test('serialize(form, {type:\'array\'})', function (complete) {
1363
+ sHelper.testFormSerializeArray(ajax.serialize, 'direct')
1364
+ complete()
1365
+ })
1366
+
1367
+ test('serialize(form, {type:\'map\'})', function (complete) {
1368
+ sHelper.testFormSerializeHash(ajax.serialize, 'direct')
1369
+ complete()
1370
+ })
1371
+
1372
+ // mainly for Ender integration, so you can do this:
1373
+ // $('input[name=T2],input[name=who],input[name=wha]').serialize()
1374
+ test('serialize(element, element, element...)', function (complete) {
1375
+ sHelper.testMultiArgumentSerialize(ajax.serialize, 'direct', PASS_ARGS)
1376
+ complete()
1377
+ })
1378
+
1379
+ // mainly for Ender integration, so you can do this:
1380
+ // $('input[name=T2],input[name=who],input[name=wha]')
1381
+ // .serialize({type:'array'})
1382
+ test('serialize(element, element, element..., {type:\'array\'})'
1383
+ , function (complete) {
1384
+ sHelper.testMultiArgumentSerializeArray(
1385
+ ajax.serialize
1386
+ , 'direct'
1387
+ , PASS_ARGS
1388
+ )
1389
+ complete()
1390
+ })
1391
+
1392
+ // mainly for Ender integration, so you can do this:
1393
+ // $('input[name=T2],input[name=who],input[name=wha]')
1394
+ // .serialize({type:'map'})
1395
+ test('serialize(element, element, element...)', function (complete) {
1396
+ sHelper.testMultiArgumentSerializeHash(
1397
+ ajax.serialize
1398
+ , 'direct'
1399
+ , PASS_ARGS
1400
+ )
1401
+ complete()
1402
+ })
1403
+
1404
+ test('toQueryString([{ name: x, value: y }, ... ]) name/value array'
1405
+ , function (complete) {
1406
+
1407
+ var arr = [
1408
+ { name: 'foo', value: 'bar' }
1409
+ , { name: 'baz', value: '' }
1410
+ , { name: 'x', value: -20 }
1411
+ , { name: 'x', value: 20 }
1412
+ ]
1413
+
1414
+ ok(ajax.toQueryString(arr) == 'foo=bar&baz=&x=-20&x=20', 'simple')
1415
+
1416
+ arr = [
1417
+ { name: 'dotted.name.intact', value: '$@%' }
1418
+ , { name: '$ $', value: 20 }
1419
+ , { name: 'leave britney alone', value: 'waa haa haa' }
1420
+ ]
1421
+
1422
+ ok(
1423
+ ajax.toQueryString(arr) ==
1424
+ 'dotted.name.intact=%24%40%25&%24+%24=20'
1425
+ + '&leave+britney+alone=waa+haa+haa'
1426
+ , 'escaping required'
1427
+ )
1428
+
1429
+ complete()
1430
+ })
1431
+
1432
+ test('toQueryString({name: value,...} complex object', function (complete) {
1433
+ var obj = { 'foo': 'bar', 'baz': '', 'x': -20 }
1434
+
1435
+ ok(ajax.toQueryString(obj) == 'foo=bar&baz=&x=-20', 'simple')
1436
+
1437
+ obj = {
1438
+ 'dotted.name.intact': '$@%'
1439
+ , '$ $': 20
1440
+ , 'leave britney alone': 'waa haa haa'
1441
+ }
1442
+ ok(
1443
+ ajax.toQueryString(obj) ==
1444
+ 'dotted.name.intact=%24%40%25&%24+%24=20'
1445
+ + '&leave+britney+alone=waa+haa+haa'
1446
+ , 'escaping required'
1447
+ )
1448
+
1449
+ complete()
1450
+ })
1451
+
1452
+ test('toQueryString({name: [ value1, value2 ...],...} object with arrays', function (complete) {
1453
+ var obj = { 'foo': 'bar', 'baz': [ '', '', 'boo!' ], 'x': [ -20, 2.2, 20 ] }
1454
+ ok(ajax.toQueryString(obj, true) == "foo=bar&baz=&baz=&baz=boo!&x=-20&x=2.2&x=20", "object with arrays")
1455
+ ok(ajax.toQueryString(obj) == "foo=bar&baz%5B%5D=&baz%5B%5D=&baz%5B%5D=boo!&x%5B%5D=-20&x%5B%5D=2.2&x%5B%5D=20")
1456
+ complete()
1457
+ })
1458
+
1459
+ test('toQueryString({name: { nestedName: value },...} object with objects', function(complete) {
1460
+ var obj = { 'foo': { 'bar': 'baz' }, 'x': [ { 'bar': 'baz' }, { 'boo': 'hiss' } ] }
1461
+ ok(ajax.toQueryString(obj) == "foo%5Bbar%5D=baz&x%5B0%5D%5Bbar%5D=baz&x%5B1%5D%5Bboo%5D=hiss", "object with objects")
1462
+ complete()
1463
+ })
1464
+
1465
+ })
1466
+
1467
+ sink('Ender Integration', function (test, ok) {
1468
+ var sHelper = createSerializeHelper(ok)
1469
+ sHelper.reset()
1470
+
1471
+ test('$.ajax alias for reqwest, not bound to boosh', 1, function () {
1472
+ ok(ender.ajax === ajax, '$.ajax is reqwest')
1473
+ })
1474
+
1475
+ // sHelper.test that you can do $.serialize(form)
1476
+ test('$.serialize(form)', function (complete) {
1477
+ sHelper.testFormSerialize(ender.serialize, 'ender')
1478
+ complete()
1479
+ })
1480
+
1481
+ // sHelper.test that you can do $.serialize(form)
1482
+ test('$.serialize(form, {type:\'array\'})', function (complete) {
1483
+ sHelper.testFormSerializeArray(ender.serialize, 'ender')
1484
+ complete()
1485
+ })
1486
+
1487
+ // sHelper.test that you can do $.serialize(form)
1488
+ test('$.serialize(form, {type:\'map\'})', function (complete) {
1489
+ sHelper.testFormSerializeHash(ender.serialize, 'ender')
1490
+ complete()
1491
+ })
1492
+
1493
+ // sHelper.test that you can do $.serializeObject(form)
1494
+ test('$.serializeArray(...) alias for serialize(..., {type:\'map\'}'
1495
+ , function (complete) {
1496
+ sHelper.verifyFormSerializeArray(
1497
+ ender.serializeArray(document.forms[0])
1498
+ , 'ender'
1499
+ )
1500
+ complete()
1501
+ })
1502
+
1503
+ test('$.serialize(element, element, element...)', function (complete) {
1504
+ sHelper.testMultiArgumentSerialize(ender.serialize, 'ender', PASS_ARGS)
1505
+ complete()
1506
+ })
1507
+
1508
+ test('$.serialize(element, element, element..., {type:\'array\'})'
1509
+ , function (complete) {
1510
+ sHelper.testMultiArgumentSerializeArray(
1511
+ ender.serialize
1512
+ , 'ender'
1513
+ , PASS_ARGS
1514
+ )
1515
+ complete()
1516
+ })
1517
+
1518
+ test('$.serialize(element, element, element..., {type:\'map\'})'
1519
+ , function (complete) {
1520
+ sHelper.testMultiArgumentSerializeHash(
1521
+ ender.serialize
1522
+ , 'ender'
1523
+ , PASS_ARGS
1524
+ )
1525
+ complete()
1526
+ })
1527
+
1528
+ test('$(element, element, element...).serialize()', function (complete) {
1529
+ sHelper.testMultiArgumentSerialize(ender.fn.serialize, 'ender', BIND_ARGS)
1530
+ complete()
1531
+ })
1532
+
1533
+ test('$(element, element, element...).serialize({type:\'array\'})'
1534
+ , function (complete) {
1535
+ sHelper.testMultiArgumentSerializeArray(
1536
+ ender.fn.serialize
1537
+ , 'ender'
1538
+ , BIND_ARGS
1539
+ )
1540
+ complete()
1541
+ })
1542
+
1543
+ test('$(element, element, element...).serialize({type:\'map\'})'
1544
+ , function (complete) {
1545
+ sHelper.testMultiArgumentSerializeHash(
1546
+ ender.fn.serialize
1547
+ , 'ender'
1548
+ , BIND_ARGS
1549
+ )
1550
+ complete()
1551
+ })
1552
+
1553
+ test('$.toQueryString alias for reqwest.toQueryString, not bound to boosh'
1554
+ , function (complete) {
1555
+ ok(
1556
+ ender.toQueryString === ajax.toQueryString
1557
+ , '$.toQueryString is reqwest.toQueryString'
1558
+ )
1559
+ complete()
1560
+ })
1561
+ })
1562
+
1563
+
1564
+ /**
1565
+ * Promise tests for `then` `fail` and `always`
1566
+ */
1567
+ sink('Promises', function (test, ok) {
1568
+
1569
+ test('always callback is called', function (complete) {
1570
+ ajax({
1571
+ url: '/tests/fixtures/fixtures.js'
1572
+ })
1573
+ .always(function () {
1574
+ ok(true, 'called complete')
1575
+ complete()
1576
+ })
1577
+ })
1578
+
1579
+ test('success and error handlers are called', 3, function () {
1580
+ ajax({
1581
+ url: '/tests/fixtures/invalidJSON.json'
1582
+ , type: 'json'
1583
+ })
1584
+ .then(
1585
+ function () {
1586
+ ok(false, 'success callback fired')
1587
+ }
1588
+ , function (resp, msg) {
1589
+ ok(
1590
+ msg == 'Could not parse JSON in response'
1591
+ , 'error callback fired'
1592
+ )
1593
+ }
1594
+ )
1595
+
1596
+ ajax({
1597
+ url: '/tests/fixtures/invalidJSON.json'
1598
+ , type: 'json'
1599
+ })
1600
+ .fail(function (resp, msg) {
1601
+ ok(msg == 'Could not parse JSON in response', 'fail callback fired')
1602
+ })
1603
+
1604
+ ajax({
1605
+ url: '/tests/fixtures/fixtures.json'
1606
+ , type: 'json'
1607
+ })
1608
+ .then(
1609
+ function () {
1610
+ ok(true, 'success callback fired')
1611
+ }
1612
+ , function () {
1613
+ ok(false, 'error callback fired')
1614
+ }
1615
+ )
1616
+ })
1617
+
1618
+ test('then & always handlers can be added after a response is received'
1619
+ , 2
1620
+ , function () {
1621
+
1622
+ var a = ajax({
1623
+ url: '/tests/fixtures/fixtures.json'
1624
+ , type: 'json'
1625
+ })
1626
+ .always(function () {
1627
+ setTimeout(function () {
1628
+ a.then(
1629
+ function () {
1630
+ ok(true, 'success callback called')
1631
+ }
1632
+ , function () {
1633
+ ok(false, 'error callback called')
1634
+ }
1635
+ ).always(function () {
1636
+ ok(true, 'complete callback called')
1637
+ })
1638
+ }, 1)
1639
+ })
1640
+ })
1641
+
1642
+ test('failure handlers can be added after a response is received'
1643
+ , function (complete) {
1644
+
1645
+ var a = ajax({
1646
+ url: '/tests/fixtures/invalidJSON.json'
1647
+ , type: 'json'
1648
+ })
1649
+ .always(function () {
1650
+ setTimeout(function () {
1651
+ a
1652
+ .fail(function () {
1653
+ ok(true, 'fail callback called')
1654
+ complete()
1655
+ })
1656
+ }, 1)
1657
+ })
1658
+ })
1659
+
1660
+ test('.then success and fail are optional parameters', 1, function () {
1661
+ try {
1662
+ ajax({
1663
+ url: '/tests/fixtures/invalidJSON.json'
1664
+ , type: 'json'
1665
+ })
1666
+ .then()
1667
+ } catch (ex) {
1668
+ ok(false, '.then() parameters should be optional')
1669
+ } finally {
1670
+ ok(true, 'passed .then() optional parameters')
1671
+ }
1672
+ })
1673
+
1674
+ })
1675
+
1676
+
1677
+
1678
+ sink('Timeout', function (test, ok) {
1679
+ test('xmlHttpRequest', function (complete) {
1680
+ var ts = +new Date()
1681
+ ajax({
1682
+ url: '/tests/timeout'
1683
+ , type: 'json'
1684
+ , timeout: 250
1685
+ , error: function (err) {
1686
+ ok(err, 'received error response')
1687
+ try {
1688
+ ok(err && err.status === 0, 'correctly caught timeout')
1689
+ } catch (e) {
1690
+ ok(true, 'IE is a troll')
1691
+ }
1692
+ var tt = Math.abs(+new Date() - ts)
1693
+ ok(
1694
+ tt > 200 && tt < 300
1695
+ , 'timeout close enough to 250 (' + tt + ')'
1696
+ )
1697
+ complete()
1698
+ }
1699
+ })
1700
+ })
1701
+
1702
+ test('jsonpRequest', function (complete) {
1703
+ var ts = +new Date()
1704
+ ajax({
1705
+ url: '/tests/timeout'
1706
+ , type: 'jsonp'
1707
+ , timeout: 250
1708
+ , error: function (err) {
1709
+ ok(err, 'received error response')
1710
+ var tt = Math.abs(+new Date() - ts)
1711
+ ok(
1712
+ tt > 200 && tt < 300
1713
+ , 'timeout close enough to 250 (' + tt + ')'
1714
+ )
1715
+ complete()
1716
+ }
1717
+ })
1718
+ })
1719
+ })
1720
+
1721
+ start()
1722
+
1723
+ }(reqwest))