wpa_cli_web 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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))