1
var suite = new Y.Test.Suite("Y.JSONPRequest and Y.jsonp with jsonp-url"),
2
// Dirty dirty hack to future proof duck type for onload where
4
onScriptLoad = (function () {
8
return function (node, callback) {
12
node.onload = function () {
13
// prefer onload to onreadystatechange
15
this.onload = this.onreadystatechange = onrsc = null;
23
node.onreadystatechange = function () {
24
if (!('loaded|complete'.indexOf(this.readyState) % 7)) {
25
// assume no onload support until onload says so.
26
// this leaks one onload function.
27
this.onreadystatechange = null;
28
// just in case onload fired first (which it shouldn't)
29
if (onrsc && !loaded) {
40
suite.add(new Y.Test.Case({
43
"config charset should be set via Y.Get.script": function () {
45
scripts = Y.all('script')._nodes,
48
Y.jsonp("server/service.php?callback={callback}", function () {});
50
newScript = Y.Array.filter(Y.all('script')._nodes, function (s) {
51
return Y.Array.indexOf(scripts, s) === -1;
54
Y.Assert.areSame("utf-8", newScript.charset);
56
scripts.push(newScript);
58
Y.jsonp("server/service.php?callback={callback}", {
60
success: function () {}
65
newScript = Y.Array.filter(Y.all('script')._nodes, function (s) {
66
return Y.Array.indexOf(scripts, s) === -1;
69
Y.Assert.areSame("GBK", newScript.getAttribute("charset"));
71
// to allow JSONP the chance to clean up the callback registry
72
// before other tests begin. Race condition, yes. The alternative
73
// was to wait() and resume() in the success callback, but for some
74
// reason Test.Runner cleared the test's wait timer before the
75
// success callback, so either the test fails because resume() is
76
// called when Test.Runner doesn't think it's waiting, OR the test
77
// fails if resume() is only called if Test.Runner thinks it is waiting
78
// (which it doesn't) so resume() is never called.
79
test.wait(function () {}, 1000);
82
"config attributes should be set via Y.Get.script": function () {
84
scripts = Y.all('script')._nodes,
87
Y.jsonp("server/service.php?callback={callback}", {
89
success: function () { test.resume(); }
92
// passing an attribute that is less likely to be skipped over
93
// by browser whitelisting (if they do that now or will later)
94
language: "javascript"
98
newScript = Y.Array.filter(Y.all('script')._nodes, function (s) {
99
return Y.Array.indexOf(scripts, s) === -1;
102
Y.Assert.areSame("javascript", newScript.getAttribute("language"));
104
// to allow JSONP the chance to clean up the callback registry before
105
// other tests begin.
110
suite.add(new Y.Test.Case({
115
// Get (v3.3) doesn't support onerror in recent webkit
116
"failure handler in callback object should execute": true
120
"callback function as second arg should be success handler": function () {
123
Y.jsonp("server/service.php?&callback={callback}", function (json) {
124
//console.log(Y.Object.keys(YUI.Env.JSONP), "callback function as second arg should be success handler");
125
self.resume(function () {
126
Y.Assert.isObject(json);
133
"success handler in callback object should execute": function () {
136
Y.jsonp("server/service.php?&callback={callback}", {
138
success: function (json) {
139
//console.log(Y.Object.keys(YUI.Env.JSONP), "success handler in callback object should execute");
140
self.resume(function () {
141
Y.Assert.isObject(json);
150
"failure handler in callback object should execute": function () {
153
Y.jsonp("server/404.php?&callback={callback}", {
155
success: function (json) {
156
self.resume(function () {
157
Y.Assert.fail("Success handler called from 404 response");
160
failure: function () {
161
//console.log("failure handler in callback object should execute");
163
self.resume(function () {});
171
"failure handler in callback object should not execute for successful io": function () {
174
Y.jsonp("server/service.php?&callback={callback}", {
176
success: function (json) {
177
//console.log(Y.Object.keys(YUI.Env.JSONP), "failure handler in callback object should not execute for successful io");
179
self.resume(function () {});
181
failure: function () {
182
self.resume(function () {
183
Y.Assert.fail("Failure handler called after successful response");
192
"test multiple send() from an instance of Y.JSONPRequest": function () {
197
service = new Y.JSONPRequest("server/service.php?callback={callback}", {
199
success: function (json) {
200
//console.log(Y.Object.keys(YUI.Env.JSONP), "test multiple send() from an instance of Y.JSONPRequest");
202
self.resume(function () {
204
Y.Assert.areSame(count, 3);
211
service.send().send().send();
216
// failure for bogus response data (not yet implemented)
217
// missing {callback} (not sure how to test. No callback would be attached.
218
// Maybe have the service create a property on YUI and have the test
219
// look for that after a time?)
220
// missing success handler (logs a warning)
221
// JSONPRequest + send
222
// JSONPRequest + send with config overrides (not yet implemented)
225
suite.add(new Y.Test.Case({
226
name : "context and args"
230
suite.add(new Y.Test.Case({
235
suite.add(new Y.Test.Case({
238
"allowCache should preserve the same callback": function () {
242
jsonp = new Y.JSONPRequest('server/service.php?&callback={callback}', {
245
success: function (data) {
246
//console.log(Y.Object.keys(YUI.Env.JSONP), "allowCache should preserve the same callback");
248
if (callback !== data.callback) {
249
test.resume(function () {
250
Y.Assert.areSame(callback, data.callback, "callback proxy name should be reused");
252
} else if (--remaining) {
255
test.resume(function () {
260
callback = data.callback;
273
"allowCache should not clear proxy if another send() is pending response":
277
jsonp = new Y.JSONPRequest('server/service.php?&callback={callback}', {
280
success: function (data) {
281
//console.log(Y.Object.keys(YUI.Env.JSONP), "allowCache should not clear proxy if another send() is pending response");
282
callbacks.push(data.callback);
284
if (callbacks.length > 2) {
285
test.resume(function () {
286
Y.Assert.areSame(callbacks[0], callbacks[1]);
287
Y.Assert.areSame(callbacks[1], callbacks[2]);
288
Y.Assert.isUndefined(YUI.Env.JSONP[callbacks[0]]);
290
} else if (!YUI.Env.JSONP[data.callback.split(/\./).pop()]) {
291
test.resume(function () {
292
Y.Assert.fail("proxy cleared prematurely");
309
suite.add(new Y.Test.Case({
312
"timeout should not flush the global proxy": function () {
314
timeoutCalled = false,
315
jsonpProxies = Y.Object.keys(YUI.Env.JSONP).length,
316
jsonp = new Y.JSONPRequest('server/service.php?&wait=2&callback={callback}', {
319
success: function (data) {
320
//console.log(Y.Object.keys(YUI.Env.JSONP), "timeout should not flush the global proxy");
321
test.resume(function () {
322
Y.Assert.fail("Success callback executed after timeout");
325
timeout: function () {
326
//console.log(Y.Object.keys(YUI.Env.JSONP), "timeout should not flush the global proxy (timeout)");
327
timeoutCalled = true;
331
scripts = Y.all('script')._nodes,
334
Y.Assert.areSame(0, jsonpProxies, "Whar these leavings from?");
338
// Success is measured by the success callback NOT being executed,
339
// but we're in an async operation, so I need something to trigger
340
// a test.resume(..). So I'm finding the added script tag and
341
// hooking a separate onload handler to it, which would execute after
342
// the success handler if it is called due to callbacks executing in
343
// subscription order. Not pretty, but better than a longer setTimeout?
344
newScript = Y.Array.filter(Y.all('script')._nodes, function (s) {
345
return Y.Array.indexOf(scripts, s) === -1;
348
onScriptLoad(newScript, function () {
349
//console.log("__yui_wait: " + test.__yui_wait + " (should be a setTimeout int)");
350
// If the success callback is triggered, it will resume the test,
351
// and clear the wait() timeout, so having another resume() here
352
// will just blow up. The test has already failed if !_waiting
353
if (Y.Test.Runner._waiting) {
354
test.resume(function () {
355
Y.Assert.isTrue(timeoutCalled);
356
Y.Assert.areSame(jsonpProxies, Y.Object.keys(YUI.Env.JSONP).length);
367
"timeout should not flush the global proxy across multiple send calls": function () {
369
// Stubbed from the test above. This test needs to contact the
370
// serverat the same url, but get varying delays. This means to
371
// properly test, the server needs to behave randomly, and this test
372
// needs to iterate until that random behavior matches the expected
373
// test behavior. Which is icky.
375
timeoutCalled = false,
376
jsonp = new Y.JSONPRequest('server/service.php?wait=2&callback={callback}', {
379
success: function (data) {
380
test.resume(function () {
381
Y.Assert.fail("Success callback executed after timeout");
384
timeout: function () {
385
timeoutCalled = true;
389
scripts = Y.all('script')._nodes,
394
newScript = Y.Array.filter(Y.all('script')._nodes, function (s) {
395
return Y.Array.indexOf(scripts, s) === -1;
398
Y.on('load', function () {
399
test.resume(function () {
400
Y.Assert.isTrue(timeoutCalled);
409
Y.Test.Runner.add(suite);