aboutsummaryrefslogtreecommitdiff
path: root/contexts/data/lib/closure-library/closure/goog/net/jsonp_test.html
blob: f016153142970af777c61bc5fa210b34c511a1bf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
<!DOCTYPE html>
<html>
<!--
Copyright 2007 The Closure Library Authors. All Rights Reserved.

Use of this source code is governed by the Apache License, Version 2.0.
See the COPYING file for details.
-->
<!--
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Closure Unit Tests - goog.net.Jsonp</title>
<script src="../base.js"></script>
<script>
  goog.require('goog.dom');
  goog.require('goog.net.Jsonp');
  goog.require('goog.testing.jsunit');
  goog.require('goog.userAgent');
  goog.require('goog.testing.recordFunction');
  goog.require('goog.testing.PropertyReplacer');
</script>
</head>
<body>
<script>
// Global vars to facilitate a shared set up function.

var timeoutWasCalled;
var timeoutHandler;

var fakeUrl = 'http://fake-site.eek/';

var originalTimeout;
function setUp() {
  timeoutWasCalled = false;
  timeoutHandler = null;
  originalTimeout = window.setTimeout;
  window.setTimeout = function(handler, time) {
    timeoutWasCalled = true;
    timeoutHandler = handler;
  };
}

// Firefox throws a JS error when a script is not found.  We catch that here and
// ensure the test case doesn't fail because of it.
var originalOnError = window.onerror;
window.onerror = function(msg, url, line) {
  // TODO(user): Safari 3 on the farm returns an object instead of the typcial
  // params.  Pass through errors for safari for now.
  if (goog.userAgent.WEBKIT ||
      msg == 'Error loading script' && url.indexOf('fake-site') != -1) {
    return true;
  } else {
    return originalOnError && originalOnError(msg, url, line);
  }
};

function tearDown() {
  window.setTimeout = originalTimeout;
}

// Quick function records the before-state of the DOM, and then return a
// a function to check that XDC isn't leaving stuff behind.
function newCleanupGuard() {
  var bodyChildCount = document.body.childNodes.length;

  return function() {
    // let any timeout queues finish before we check these:
    window.setTimeout(function() {
      var propCounter = 0;

      // All callbacks should have been deleted or be the null function.
      for (var id in goog.global[goog.net.Jsonp.CALLBACKS]) {
        if (goog.global[goog.net.Jsonp.CALLBACKS][id] != goog.nullFunction) {
          propCounter++;
        }
      }

      assertEquals(
          'script cleanup', bodyChildCount, document.body.childNodes.length);
      assertEquals('window jsonp array empty', 0, propCounter);
    }, 0);
  }
}

function getScriptElement(result) {
  return result.deferred_.defaultScope_.script_;
}


// Check that send function is sane when things go well.
function testSend() {
  var replyReceived;
  var jsonp = new goog.net.Jsonp(fakeUrl);

  var checkCleanup = newCleanupGuard();

  var userCallback = function(data) {
    replyReceived = data;
  }

  var payload = {atisket: 'atasket', basket: 'yellow'};
  var result = jsonp.send(payload, userCallback);

  var script = getScriptElement(result);

  assertNotNull('script created', script);
  assertEquals('encoding is utf-8', 'UTF-8', script.charset);

  // Check that the URL matches our payload.
  assertTrue('payload in url', script.src.indexOf('basket=yellow') > -1);
  assertTrue('server url', script.src.indexOf(fakeUrl) == 0);

  // Now, we have to track down the name of the callback function, so we can
  // call that to simulate a returned request + verify that the callback
  // function does not break if it receives a second unexpected parameter.
  var callbackName = /callback=([^&]+)/.exec(script.src)[1];
  var callbackFunc = eval(callbackName);
  callbackFunc({some: 'data', another: ['data', 'right', 'here']},
      'unexpected');
  assertEquals('input was received', 'right', replyReceived.another[1]);

  // Because the callbackFunc calls cleanUp_ and that calls setTimeout which
  // we have overwritten, we have to call the timeoutHandler to actually do
  // the cleaning.
  timeoutHandler();

  checkCleanup();
  timeoutHandler();
}


// Check that send function is sane when things go well.
function testSendWhenCallbackHasTwoParameters() {
  var replyReceived, replyReceived2;
  var jsonp = new goog.net.Jsonp(fakeUrl);

  var checkCleanup = newCleanupGuard();

  var userCallback = function(data, opt_data2) {
    replyReceived = data;
    replyReceived2 = opt_data2;
  }

  var payload = {atisket: 'atasket', basket: 'yellow'};
  var result = jsonp.send(payload, userCallback);
  var script = getScriptElement(result);

  // Test a callback function that receives two parameters.
  var callbackName = /callback=([^&]+)/.exec(script.src)[1];
  var callbackFunc = eval(callbackName);
  callbackFunc('param1', {some: 'data', another: ['data', 'right', 'here']});
  assertEquals('input was received', 'param1', replyReceived);
  assertEquals('second input was received', 'right',
      replyReceived2.another[1]);

  // Because the callbackFunc calls cleanUp_ and that calls setTimeout which
  // we have overwritten, we have to call the timeoutHandler to actually do
  // the cleaning.
  timeoutHandler();

  checkCleanup();
  timeoutHandler();
}

// Check that send function works correctly when callback param value is
// specified.
function testSendWithCallbackParamValue() {
  var replyReceived;
  var jsonp = new goog.net.Jsonp(fakeUrl);

  var checkCleanup = newCleanupGuard();

  var userCallback = function(data) {
    replyReceived = data;
  }

  var payload = {atisket: 'atasket', basket: 'yellow'};
  var result = jsonp.send(payload, userCallback, undefined, 'dummyId');

  var script = getScriptElement(result);

  assertNotNull('script created', script);
  assertEquals('encoding is utf-8', 'UTF-8', script.charset);

  // Check that the URL matches our payload.
  assertTrue('payload in url', script.src.indexOf('basket=yellow') > -1);
  assertTrue('dummyId in url',
      script.src.indexOf('callback=_callbacks_.dummyId') > -1);
  assertTrue('server url', script.src.indexOf(fakeUrl) == 0);

  // Now, we simulate a returned request using the known callback function
  // name.
  var callbackFunc = _callbacks_.dummyId;
  callbackFunc({some: 'data', another: ['data', 'right', 'here']});
  assertEquals('input was received', 'right', replyReceived.another[1]);

  // Because the callbackFunc calls cleanUp_ and that calls setTimeout which
  // we have overwritten, we have to call the timeoutHandler to actually do
  // the cleaning.
  timeoutHandler();

  checkCleanup();
  timeoutHandler();
}


// Check that the send function is sane when the thing goes south.
function testSendFailure() {
  var replyReceived = false;
  var errorReplyReceived = false;

  var jsonp = new goog.net.Jsonp(fakeUrl);

  var checkCleanup = newCleanupGuard();

  var userCallback = function(data) {
    replyReceived = data;
  }
  var userErrorCallback = function(data) {
    errorReplyReceived = data;
  }

  var payload = { justa: 'test' };

  jsonp.send(payload, userCallback, userErrorCallback);

  assertTrue('timeout called', timeoutWasCalled);

  // Now, simulate the time running out, so we go into error mode.
  // After jsonp.send(), the timeoutHandler now is the Jsonp.cleanUp_ function.
  timeoutHandler();
  // But that function also calls a setTimeout(), so it changes the timeout
  // handler once again, so to actually clean up we have to call the
  // timeoutHandler() once again. Fun!
  timeoutHandler();

  assertFalse('standard callback not called', replyReceived);

  // The user's error handler should be called back with the same payload
  // passed back to it.
  assertEquals('error handler called', 'test', errorReplyReceived.justa);

  // Check that the relevant cleanup has occurred.
  checkCleanup();
  // Check cleanup just calls setTimeout so we have to call the handler to
  // actually check that the cleanup worked.
  timeoutHandler();
}


// Check that a cancel call works and cleans up after itself.
function testCancel() {
  var checkCleanup = newCleanupGuard();

  var successCalled = false;
  var successCallback = function() {
    successCalled = true;
  };

  // Send and cancel a request, then make sure it was cleaned up.
  var jsonp = new goog.net.Jsonp(fakeUrl);
  var requestObject = jsonp.send({test: 'foo'}, successCallback);
  jsonp.cancel(requestObject);

  for (var key in goog.global[goog.net.Jsonp.CALLBACKS]) {
    assertNotEquals('The success callback should have been removed',
                    goog.global[goog.net.Jsonp.CALLBACKS][key],
                    successCallback);
  }

  // Make sure cancelling removes the script tag
  checkCleanup();
  timeoutHandler();
}

function testPayloadParameters() {
  var checkCleanup = newCleanupGuard();

  var jsonp = new goog.net.Jsonp(fakeUrl);
  var result = jsonp.send({
    'foo': 3,
    'bar': 'baz'
  });

  var script = getScriptElement(result);
  assertEquals('Payload parameters should have been added to url.',
               fakeUrl + '?foo=3&bar=baz',
               script.src);

  checkCleanup();
  timeoutHandler();
}

function testOptionalPayload() {
  var checkCleanup = newCleanupGuard();

  var errorCallback = goog.testing.recordFunction();

  var stubs = new goog.testing.PropertyReplacer();
  stubs.set(goog.global, 'setTimeout', function(errorHandler) {
    errorHandler();
  });

  var jsonp = new goog.net.Jsonp(fakeUrl);
  var result = jsonp.send(null, null, errorCallback);

  var script = getScriptElement(result);
  assertEquals('Parameters should not have been added to url.',
               fakeUrl, script.src);

  // Clear the script hooks because we triggered the error manually.
  script.onload = goog.nullFunction;
  script.onerror = goog.nullFunction;
  script.onreadystatechange = goog.nullFunction;

  var errorCallbackArguments = errorCallback.getLastCall().getArguments();
  assertEquals(1, errorCallbackArguments.length);
  assertNull(errorCallbackArguments[0]);

  checkCleanup();
  stubs.reset();
}

</script>
</body>
</html>