ember-source 1.9.0.alpha.2 → 1.9.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ember-source might be problematic. Click here for more details.

@@ -2,6 +2,11 @@
2
2
  var Ember = { assert: function() {}, FEATURES: { isEnabled: function() {} } };
3
3
  /* global Handlebars:true */
4
4
 
5
+ // Remove "use strict"; from transpiled module (in browser builds only) until
6
+ // https://bugs.webkit.org/show_bug.cgi?id=138038 is fixed
7
+ //
8
+ // REMOVE_USE_STRICT: true
9
+
5
10
  /**
6
11
  @module ember
7
12
  @submodule ember-handlebars-compiler
@@ -0,0 +1,1529 @@
1
+ /*!
2
+ * @overview Ember - JavaScript Application Framework
3
+ * @copyright Copyright 2011-2014 Tilde Inc. and contributors
4
+ * Portions Copyright 2006-2011 Strobe Inc.
5
+ * Portions Copyright 2008-2011 Apple Inc. All rights reserved.
6
+ * @license Licensed under MIT license
7
+ * See https://raw.github.com/emberjs/ember.js/master/LICENSE
8
+ * @version 1.9.0-beta.1
9
+ */
10
+
11
+ (function() {
12
+ var enifed, requireModule, eriuqer, requirejs, Ember;
13
+
14
+ (function() {
15
+ Ember = this.Ember = this.Ember || {};
16
+ if (typeof Ember === 'undefined') { Ember = {}; };
17
+
18
+ if (typeof Ember.__loader === 'undefined') {
19
+ var registry = {}, seen = {};
20
+
21
+ enifed = function(name, deps, callback) {
22
+ registry[name] = { deps: deps, callback: callback };
23
+ };
24
+
25
+ requirejs = eriuqer = requireModule = function(name) {
26
+ if (seen.hasOwnProperty(name)) { return seen[name]; }
27
+ seen[name] = {};
28
+
29
+ if (!registry[name]) {
30
+ throw new Error("Could not find module " + name);
31
+ }
32
+
33
+ var mod = registry[name];
34
+ var deps = mod.deps;
35
+ var callback = mod.callback;
36
+ var reified = [];
37
+ var exports;
38
+
39
+ for (var i=0, l=deps.length; i<l; i++) {
40
+ if (deps[i] === 'exports') {
41
+ reified.push(exports = {});
42
+ } else {
43
+ reified.push(requireModule(resolve(deps[i])));
44
+ }
45
+ }
46
+
47
+ var value = callback.apply(this, reified);
48
+ return seen[name] = exports || value;
49
+
50
+ function resolve(child) {
51
+ if (child.charAt(0) !== '.') { return child; }
52
+ var parts = child.split("/");
53
+ var parentBase = name.split("/").slice(0, -1);
54
+
55
+ for (var i=0, l=parts.length; i<l; i++) {
56
+ var part = parts[i];
57
+
58
+ if (part === '..') { parentBase.pop(); }
59
+ else if (part === '.') { continue; }
60
+ else { parentBase.push(part); }
61
+ }
62
+
63
+ return parentBase.join("/");
64
+ }
65
+ };
66
+ requirejs._eak_seen = registry;
67
+
68
+ Ember.__loader = {define: enifed, require: eriuqer, registry: registry};
69
+ } else {
70
+ enifed = Ember.__loader.define;
71
+ requirejs = eriuqer = requireModule = Ember.__loader.require;
72
+ }
73
+ })();
74
+
75
+ enifed("ember-debug",
76
+ ["ember-metal/core","ember-metal/error","ember-metal/logger","exports"],
77
+ function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
78
+ "use strict";
79
+ /*global __fail__*/
80
+
81
+ var Ember = __dependency1__["default"];
82
+ var EmberError = __dependency2__["default"];
83
+ var Logger = __dependency3__["default"];
84
+
85
+ /**
86
+ Ember Debug
87
+
88
+ @module ember
89
+ @submodule ember-debug
90
+ */
91
+
92
+ /**
93
+ @class Ember
94
+ */
95
+
96
+ /**
97
+ Define an assertion that will throw an exception if the condition is not
98
+ met. Ember build tools will remove any calls to `Ember.assert()` when
99
+ doing a production build. Example:
100
+
101
+ ```javascript
102
+ // Test for truthiness
103
+ Ember.assert('Must pass a valid object', obj);
104
+
105
+ // Fail unconditionally
106
+ Ember.assert('This code path should never be run');
107
+ ```
108
+
109
+ @method assert
110
+ @param {String} desc A description of the assertion. This will become
111
+ the text of the Error thrown if the assertion fails.
112
+ @param {Boolean} test Must be truthy for the assertion to pass. If
113
+ falsy, an exception will be thrown.
114
+ */
115
+ Ember.assert = function(desc, test) {
116
+ if (!test) {
117
+ throw new EmberError("Assertion Failed: " + desc);
118
+ }
119
+ };
120
+
121
+
122
+ /**
123
+ Display a warning with the provided message. Ember build tools will
124
+ remove any calls to `Ember.warn()` when doing a production build.
125
+
126
+ @method warn
127
+ @param {String} message A warning to display.
128
+ @param {Boolean} test An optional boolean. If falsy, the warning
129
+ will be displayed.
130
+ */
131
+ Ember.warn = function(message, test) {
132
+ if (!test) {
133
+ Logger.warn("WARNING: "+message);
134
+ if ('trace' in Logger) Logger.trace();
135
+ }
136
+ };
137
+
138
+ /**
139
+ Display a debug notice. Ember build tools will remove any calls to
140
+ `Ember.debug()` when doing a production build.
141
+
142
+ ```javascript
143
+ Ember.debug('I\'m a debug notice!');
144
+ ```
145
+
146
+ @method debug
147
+ @param {String} message A debug message to display.
148
+ */
149
+ Ember.debug = function(message) {
150
+ Logger.debug("DEBUG: "+message);
151
+ };
152
+
153
+ /**
154
+ Display a deprecation warning with the provided message and a stack trace
155
+ (Chrome and Firefox only). Ember build tools will remove any calls to
156
+ `Ember.deprecate()` when doing a production build.
157
+
158
+ @method deprecate
159
+ @param {String} message A description of the deprecation.
160
+ @param {Boolean} test An optional boolean. If falsy, the deprecation
161
+ will be displayed.
162
+ */
163
+ Ember.deprecate = function(message, test) {
164
+ if (test) { return; }
165
+
166
+ if (Ember.ENV.RAISE_ON_DEPRECATION) { throw new EmberError(message); }
167
+
168
+ var error;
169
+
170
+ // When using new Error, we can't do the arguments check for Chrome. Alternatives are welcome
171
+ try { __fail__.fail(); } catch (e) { error = e; }
172
+
173
+ if (Ember.LOG_STACKTRACE_ON_DEPRECATION && error.stack) {
174
+ var stack;
175
+ var stackStr = '';
176
+
177
+ if (error['arguments']) {
178
+ // Chrome
179
+ stack = error.stack.replace(/^\s+at\s+/gm, '').
180
+ replace(/^([^\(]+?)([\n$])/gm, '{anonymous}($1)$2').
181
+ replace(/^Object.<anonymous>\s*\(([^\)]+)\)/gm, '{anonymous}($1)').split('\n');
182
+ stack.shift();
183
+ } else {
184
+ // Firefox
185
+ stack = error.stack.replace(/(?:\n@:0)?\s+$/m, '').
186
+ replace(/^\(/gm, '{anonymous}(').split('\n');
187
+ }
188
+
189
+ stackStr = "\n " + stack.slice(2).join("\n ");
190
+ message = message + stackStr;
191
+ }
192
+
193
+ Logger.warn("DEPRECATION: "+message);
194
+ };
195
+
196
+
197
+
198
+ /**
199
+ Alias an old, deprecated method with its new counterpart.
200
+
201
+ Display a deprecation warning with the provided message and a stack trace
202
+ (Chrome and Firefox only) when the assigned method is called.
203
+
204
+ Ember build tools will not remove calls to `Ember.deprecateFunc()`, though
205
+ no warnings will be shown in production.
206
+
207
+ ```javascript
208
+ Ember.oldMethod = Ember.deprecateFunc('Please use the new, updated method', Ember.newMethod);
209
+ ```
210
+
211
+ @method deprecateFunc
212
+ @param {String} message A description of the deprecation.
213
+ @param {Function} func The new function called to replace its deprecated counterpart.
214
+ @return {Function} a new function that wrapped the original function with a deprecation warning
215
+ */
216
+ Ember.deprecateFunc = function(message, func) {
217
+ return function() {
218
+ Ember.deprecate(message);
219
+ return func.apply(this, arguments);
220
+ };
221
+ };
222
+
223
+
224
+ /**
225
+ Run a function meant for debugging. Ember build tools will remove any calls to
226
+ `Ember.runInDebug()` when doing a production build.
227
+
228
+ ```javascript
229
+ Ember.runInDebug(function() {
230
+ Ember.Handlebars.EachView.reopen({
231
+ didInsertElement: function() {
232
+ console.log('I\'m happy');
233
+ }
234
+ });
235
+ });
236
+ ```
237
+
238
+ @method runInDebug
239
+ @param {Function} func The function to be executed.
240
+ @since 1.5.0
241
+ */
242
+ Ember.runInDebug = function(func) {
243
+ func();
244
+ };
245
+
246
+ /**
247
+ Will call `Ember.warn()` if ENABLE_ALL_FEATURES, ENABLE_OPTIONAL_FEATURES, or
248
+ any specific FEATURES flag is truthy.
249
+
250
+ This method is called automatically in debug canary builds.
251
+
252
+ @private
253
+ @method _warnIfUsingStrippedFeatureFlags
254
+ @return {void}
255
+ */
256
+ function _warnIfUsingStrippedFeatureFlags(FEATURES, featuresWereStripped) {
257
+ if (featuresWereStripped) {
258
+ Ember.warn('Ember.ENV.ENABLE_ALL_FEATURES is only available in canary builds.', !Ember.ENV.ENABLE_ALL_FEATURES);
259
+ Ember.warn('Ember.ENV.ENABLE_OPTIONAL_FEATURES is only available in canary builds.', !Ember.ENV.ENABLE_OPTIONAL_FEATURES);
260
+
261
+ for (var key in FEATURES) {
262
+ if (FEATURES.hasOwnProperty(key) && key !== 'isEnabled') {
263
+ Ember.warn('FEATURE["' + key + '"] is set as enabled, but FEATURE flags are only available in canary builds.', !FEATURES[key]);
264
+ }
265
+ }
266
+ }
267
+ }
268
+
269
+ __exports__._warnIfUsingStrippedFeatureFlags = _warnIfUsingStrippedFeatureFlags;if (!Ember.testing) {
270
+ // Complain if they're using FEATURE flags in builds other than canary
271
+ Ember.FEATURES['features-stripped-test'] = true;
272
+ var featuresWereStripped = true;
273
+
274
+
275
+ delete Ember.FEATURES['features-stripped-test'];
276
+ _warnIfUsingStrippedFeatureFlags(Ember.ENV.FEATURES, featuresWereStripped);
277
+
278
+ // Inform the developer about the Ember Inspector if not installed.
279
+ var isFirefox = typeof InstallTrigger !== 'undefined';
280
+ var isChrome = !!window.chrome && !window.opera;
281
+
282
+ if (typeof window !== 'undefined' && (isFirefox || isChrome) && window.addEventListener) {
283
+ window.addEventListener("load", function() {
284
+ if (document.documentElement && document.documentElement.dataset && !document.documentElement.dataset.emberExtension) {
285
+ var downloadURL;
286
+
287
+ if(isChrome) {
288
+ downloadURL = 'https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi';
289
+ } else if(isFirefox) {
290
+ downloadURL = 'https://addons.mozilla.org/en-US/firefox/addon/ember-inspector/';
291
+ }
292
+
293
+ Ember.debug('For more advanced debugging, install the Ember Inspector from ' + downloadURL);
294
+ }
295
+ }, false);
296
+ }
297
+ }
298
+ });
299
+ enifed("ember-testing",
300
+ ["ember-metal/core","ember-testing/initializers","ember-testing/support","ember-testing/setup_for_testing","ember-testing/test","ember-testing/adapters/adapter","ember-testing/adapters/qunit","ember-testing/helpers"],
301
+ function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__) {
302
+ "use strict";
303
+ var Ember = __dependency1__["default"];
304
+
305
+ // to setup initializer
306
+ // to handle various edge cases
307
+
308
+ var setupForTesting = __dependency4__["default"];
309
+ var Test = __dependency5__["default"];
310
+ var Adapter = __dependency6__["default"];
311
+ var QUnitAdapter = __dependency7__["default"];
312
+ // adds helpers to helpers object in Test
313
+
314
+ /**
315
+ Ember Testing
316
+
317
+ @module ember
318
+ @submodule ember-testing
319
+ @requires ember-application
320
+ */
321
+
322
+ Ember.Test = Test;
323
+ Ember.Test.Adapter = Adapter;
324
+ Ember.Test.QUnitAdapter = QUnitAdapter;
325
+ Ember.setupForTesting = setupForTesting;
326
+ });
327
+ enifed("ember-testing/adapters/adapter",
328
+ ["ember-metal/core","ember-runtime/system/object","exports"],
329
+ function(__dependency1__, __dependency2__, __exports__) {
330
+ "use strict";
331
+ var Ember = __dependency1__["default"];
332
+ // Ember.K
333
+ var EmberObject = __dependency2__["default"];
334
+
335
+ /**
336
+ @module ember
337
+ @submodule ember-testing
338
+ */
339
+
340
+ /**
341
+ The primary purpose of this class is to create hooks that can be implemented
342
+ by an adapter for various test frameworks.
343
+
344
+ @class Adapter
345
+ @namespace Ember.Test
346
+ */
347
+ var Adapter = EmberObject.extend({
348
+ /**
349
+ This callback will be called whenever an async operation is about to start.
350
+
351
+ Override this to call your framework's methods that handle async
352
+ operations.
353
+
354
+ @public
355
+ @method asyncStart
356
+ */
357
+ asyncStart: Ember.K,
358
+
359
+ /**
360
+ This callback will be called whenever an async operation has completed.
361
+
362
+ @public
363
+ @method asyncEnd
364
+ */
365
+ asyncEnd: Ember.K,
366
+
367
+ /**
368
+ Override this method with your testing framework's false assertion.
369
+ This function is called whenever an exception occurs causing the testing
370
+ promise to fail.
371
+
372
+ QUnit example:
373
+
374
+ ```javascript
375
+ exception: function(error) {
376
+ ok(false, error);
377
+ };
378
+ ```
379
+
380
+ @public
381
+ @method exception
382
+ @param {String} error The exception to be raised.
383
+ */
384
+ exception: function(error) {
385
+ throw error;
386
+ }
387
+ });
388
+
389
+ __exports__["default"] = Adapter;
390
+ });
391
+ enifed("ember-testing/adapters/qunit",
392
+ ["ember-testing/adapters/adapter","ember-metal/utils","exports"],
393
+ function(__dependency1__, __dependency2__, __exports__) {
394
+ "use strict";
395
+ var Adapter = __dependency1__["default"];
396
+ var inspect = __dependency2__.inspect;
397
+
398
+ /**
399
+ This class implements the methods defined by Ember.Test.Adapter for the
400
+ QUnit testing framework.
401
+
402
+ @class QUnitAdapter
403
+ @namespace Ember.Test
404
+ @extends Ember.Test.Adapter
405
+ */
406
+ __exports__["default"] = Adapter.extend({
407
+ asyncStart: function() {
408
+ QUnit.stop();
409
+ },
410
+ asyncEnd: function() {
411
+ QUnit.start();
412
+ },
413
+ exception: function(error) {
414
+ ok(false, inspect(error));
415
+ }
416
+ });
417
+ });
418
+ enifed("ember-testing/helpers",
419
+ ["ember-metal/property_get","ember-metal/error","ember-metal/run_loop","ember-views/system/jquery","ember-testing/test"],
420
+ function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__) {
421
+ "use strict";
422
+ var get = __dependency1__.get;
423
+ var EmberError = __dependency2__["default"];
424
+ var run = __dependency3__["default"];
425
+ var jQuery = __dependency4__["default"];
426
+ var Test = __dependency5__["default"];
427
+
428
+ /**
429
+ * @module ember
430
+ * @submodule ember-testing
431
+ */
432
+
433
+ var helper = Test.registerHelper;
434
+ var asyncHelper = Test.registerAsyncHelper;
435
+ var countAsync = 0;
436
+
437
+ function currentRouteName(app){
438
+ var appController = app.__container__.lookup('controller:application');
439
+
440
+ return get(appController, 'currentRouteName');
441
+ }
442
+
443
+ function currentPath(app){
444
+ var appController = app.__container__.lookup('controller:application');
445
+
446
+ return get(appController, 'currentPath');
447
+ }
448
+
449
+ function currentURL(app){
450
+ var router = app.__container__.lookup('router:main');
451
+
452
+ return get(router, 'location').getURL();
453
+ }
454
+
455
+ function pauseTest(){
456
+ Test.adapter.asyncStart();
457
+ return new Ember.RSVP.Promise(function(){ }, 'TestAdapter paused promise');
458
+ }
459
+
460
+ function visit(app, url) {
461
+ var router = app.__container__.lookup('router:main');
462
+ router.location.setURL(url);
463
+
464
+ if (app._readinessDeferrals > 0) {
465
+ router['initialURL'] = url;
466
+ run(app, 'advanceReadiness');
467
+ delete router['initialURL'];
468
+ } else {
469
+ run(app, app.handleURL, url);
470
+ }
471
+
472
+ return app.testHelpers.wait();
473
+ }
474
+
475
+ function click(app, selector, context) {
476
+ var $el = app.testHelpers.findWithAssert(selector, context);
477
+ run($el, 'mousedown');
478
+
479
+ if ($el.is(':input')) {
480
+ var type = $el.prop('type');
481
+ if (type !== 'checkbox' && type !== 'radio' && type !== 'hidden') {
482
+ run($el, function(){
483
+ // Firefox does not trigger the `focusin` event if the window
484
+ // does not have focus. If the document doesn't have focus just
485
+ // use trigger('focusin') instead.
486
+ if (!document.hasFocus || document.hasFocus()) {
487
+ this.focus();
488
+ } else {
489
+ this.trigger('focusin');
490
+ }
491
+ });
492
+ }
493
+ }
494
+
495
+ run($el, 'mouseup');
496
+ run($el, 'click');
497
+
498
+ return app.testHelpers.wait();
499
+ }
500
+
501
+ function triggerEvent(app, selector, contextOrType, typeOrOptions, possibleOptions){
502
+ var arity = arguments.length;
503
+ var context, type, options;
504
+
505
+ if (arity === 3) {
506
+ // context and options are optional, so this is
507
+ // app, selector, type
508
+ context = null;
509
+ type = contextOrType;
510
+ options = {};
511
+ } else if (arity === 4) {
512
+ // context and options are optional, so this is
513
+ if (typeof typeOrOptions === "object") { // either
514
+ // app, selector, type, options
515
+ context = null;
516
+ type = contextOrType;
517
+ options = typeOrOptions;
518
+ } else { // or
519
+ // app, selector, context, type
520
+ context = contextOrType;
521
+ type = typeOrOptions;
522
+ options = {};
523
+ }
524
+ } else {
525
+ context = contextOrType;
526
+ type = typeOrOptions;
527
+ options = possibleOptions;
528
+ }
529
+
530
+ var $el = app.testHelpers.findWithAssert(selector, context);
531
+
532
+ var event = jQuery.Event(type, options);
533
+
534
+ run($el, 'trigger', event);
535
+
536
+ return app.testHelpers.wait();
537
+ }
538
+
539
+ function keyEvent(app, selector, contextOrType, typeOrKeyCode, keyCode) {
540
+ var context, type;
541
+
542
+ if (typeof keyCode === 'undefined') {
543
+ context = null;
544
+ keyCode = typeOrKeyCode;
545
+ type = contextOrType;
546
+ } else {
547
+ context = contextOrType;
548
+ type = typeOrKeyCode;
549
+ }
550
+
551
+ return app.testHelpers.triggerEvent(selector, context, type, { keyCode: keyCode, which: keyCode });
552
+ }
553
+
554
+ function fillIn(app, selector, contextOrText, text) {
555
+ var $el, context;
556
+ if (typeof text === 'undefined') {
557
+ text = contextOrText;
558
+ } else {
559
+ context = contextOrText;
560
+ }
561
+ $el = app.testHelpers.findWithAssert(selector, context);
562
+ run(function() {
563
+ $el.val(text).change();
564
+ });
565
+ return app.testHelpers.wait();
566
+ }
567
+
568
+ function findWithAssert(app, selector, context) {
569
+ var $el = app.testHelpers.find(selector, context);
570
+ if ($el.length === 0) {
571
+ throw new EmberError("Element " + selector + " not found.");
572
+ }
573
+ return $el;
574
+ }
575
+
576
+ function find(app, selector, context) {
577
+ var $el;
578
+ context = context || get(app, 'rootElement');
579
+ $el = app.$(selector, context);
580
+
581
+ return $el;
582
+ }
583
+
584
+ function andThen(app, callback) {
585
+ return app.testHelpers.wait(callback(app));
586
+ }
587
+
588
+ function wait(app, value) {
589
+ return Test.promise(function(resolve) {
590
+ // If this is the first async promise, kick off the async test
591
+ if (++countAsync === 1) {
592
+ Test.adapter.asyncStart();
593
+ }
594
+
595
+ // Every 10ms, poll for the async thing to have finished
596
+ var watcher = setInterval(function() {
597
+ // 1. If the router is loading, keep polling
598
+ var routerIsLoading = !!app.__container__.lookup('router:main').router.activeTransition;
599
+ if (routerIsLoading) { return; }
600
+
601
+ // 2. If there are pending Ajax requests, keep polling
602
+ if (Test.pendingAjaxRequests) { return; }
603
+
604
+ // 3. If there are scheduled timers or we are inside of a run loop, keep polling
605
+ if (run.hasScheduledTimers() || run.currentRunLoop) { return; }
606
+ if (Test.waiters && Test.waiters.any(function(waiter) {
607
+ var context = waiter[0];
608
+ var callback = waiter[1];
609
+ return !callback.call(context);
610
+ })) { return; }
611
+ // Stop polling
612
+ clearInterval(watcher);
613
+
614
+ // If this is the last async promise, end the async test
615
+ if (--countAsync === 0) {
616
+ Test.adapter.asyncEnd();
617
+ }
618
+
619
+ // Synchronously resolve the promise
620
+ run(null, resolve, value);
621
+ }, 10);
622
+ });
623
+
624
+ }
625
+
626
+
627
+ /**
628
+ * Loads a route, sets up any controllers, and renders any templates associated
629
+ * with the route as though a real user had triggered the route change while
630
+ * using your app.
631
+ *
632
+ * Example:
633
+ *
634
+ * ```javascript
635
+ * visit('posts/index').then(function() {
636
+ * // assert something
637
+ * });
638
+ * ```
639
+ *
640
+ * @method visit
641
+ * @param {String} url the name of the route
642
+ * @return {RSVP.Promise}
643
+ */
644
+ asyncHelper('visit', visit);
645
+
646
+ /**
647
+ * Clicks an element and triggers any actions triggered by the element's `click`
648
+ * event.
649
+ *
650
+ * Example:
651
+ *
652
+ * ```javascript
653
+ * click('.some-jQuery-selector').then(function() {
654
+ * // assert something
655
+ * });
656
+ * ```
657
+ *
658
+ * @method click
659
+ * @param {String} selector jQuery selector for finding element on the DOM
660
+ * @return {RSVP.Promise}
661
+ */
662
+ asyncHelper('click', click);
663
+
664
+ /**
665
+ * Simulates a key event, e.g. `keypress`, `keydown`, `keyup` with the desired keyCode
666
+ *
667
+ * Example:
668
+ *
669
+ * ```javascript
670
+ * keyEvent('.some-jQuery-selector', 'keypress', 13).then(function() {
671
+ * // assert something
672
+ * });
673
+ * ```
674
+ *
675
+ * @method keyEvent
676
+ * @param {String} selector jQuery selector for finding element on the DOM
677
+ * @param {String} type the type of key event, e.g. `keypress`, `keydown`, `keyup`
678
+ * @param {Number} keyCode the keyCode of the simulated key event
679
+ * @return {RSVP.Promise}
680
+ * @since 1.5.0
681
+ */
682
+ asyncHelper('keyEvent', keyEvent);
683
+
684
+ /**
685
+ * Fills in an input element with some text.
686
+ *
687
+ * Example:
688
+ *
689
+ * ```javascript
690
+ * fillIn('#email', 'you@example.com').then(function() {
691
+ * // assert something
692
+ * });
693
+ * ```
694
+ *
695
+ * @method fillIn
696
+ * @param {String} selector jQuery selector finding an input element on the DOM
697
+ * to fill text with
698
+ * @param {String} text text to place inside the input element
699
+ * @return {RSVP.Promise}
700
+ */
701
+ asyncHelper('fillIn', fillIn);
702
+
703
+ /**
704
+ * Finds an element in the context of the app's container element. A simple alias
705
+ * for `app.$(selector)`.
706
+ *
707
+ * Example:
708
+ *
709
+ * ```javascript
710
+ * var $el = find('.my-selector');
711
+ * ```
712
+ *
713
+ * @method find
714
+ * @param {String} selector jQuery string selector for element lookup
715
+ * @return {Object} jQuery object representing the results of the query
716
+ */
717
+ helper('find', find);
718
+
719
+ /**
720
+ * Like `find`, but throws an error if the element selector returns no results.
721
+ *
722
+ * Example:
723
+ *
724
+ * ```javascript
725
+ * var $el = findWithAssert('.doesnt-exist'); // throws error
726
+ * ```
727
+ *
728
+ * @method findWithAssert
729
+ * @param {String} selector jQuery selector string for finding an element within
730
+ * the DOM
731
+ * @return {Object} jQuery object representing the results of the query
732
+ * @throws {Error} throws error if jQuery object returned has a length of 0
733
+ */
734
+ helper('findWithAssert', findWithAssert);
735
+
736
+ /**
737
+ Causes the run loop to process any pending events. This is used to ensure that
738
+ any async operations from other helpers (or your assertions) have been processed.
739
+
740
+ This is most often used as the return value for the helper functions (see 'click',
741
+ 'fillIn','visit',etc).
742
+
743
+ Example:
744
+
745
+ ```javascript
746
+ Ember.Test.registerAsyncHelper('loginUser', function(app, username, password) {
747
+ visit('secured/path/here')
748
+ .fillIn('#username', username)
749
+ .fillIn('#password', username)
750
+ .click('.submit')
751
+
752
+ return app.testHelpers.wait();
753
+ });
754
+
755
+ @method wait
756
+ @param {Object} value The value to be returned.
757
+ @return {RSVP.Promise}
758
+ */
759
+ asyncHelper('wait', wait);
760
+ asyncHelper('andThen', andThen);
761
+
762
+
763
+ /**
764
+ Returns the currently active route name.
765
+
766
+ Example:
767
+
768
+ ```javascript
769
+ function validateRouteName(){
770
+ equal(currentRouteName(), 'some.path', "correct route was transitioned into.");
771
+ }
772
+
773
+ visit('/some/path').then(validateRouteName)
774
+ ```
775
+
776
+ @method currentRouteName
777
+ @return {Object} The name of the currently active route.
778
+ @since 1.5.0
779
+ */
780
+ helper('currentRouteName', currentRouteName);
781
+
782
+ /**
783
+ Returns the current path.
784
+
785
+ Example:
786
+
787
+ ```javascript
788
+ function validateURL(){
789
+ equal(currentPath(), 'some.path.index', "correct path was transitioned into.");
790
+ }
791
+
792
+ click('#some-link-id').then(validateURL);
793
+ ```
794
+
795
+ @method currentPath
796
+ @return {Object} The currently active path.
797
+ @since 1.5.0
798
+ */
799
+ helper('currentPath', currentPath);
800
+
801
+ /**
802
+ Returns the current URL.
803
+
804
+ Example:
805
+
806
+ ```javascript
807
+ function validateURL(){
808
+ equal(currentURL(), '/some/path', "correct URL was transitioned into.");
809
+ }
810
+
811
+ click('#some-link-id').then(validateURL);
812
+ ```
813
+
814
+ @method currentURL
815
+ @return {Object} The currently active URL.
816
+ @since 1.5.0
817
+ */
818
+ helper('currentURL', currentURL);
819
+
820
+
821
+ /**
822
+ Pauses the current test - this is useful for debugging while testing or for test-driving.
823
+ It allows you to inspect the state of your application at any point.
824
+
825
+ Example (The test will pause before clicking the button):
826
+
827
+ ```javascript
828
+ visit('/')
829
+ return pauseTest();
830
+
831
+ click('.btn');
832
+ ```
833
+
834
+ @method pauseTest
835
+ @return {Object} A promise that will never resolve
836
+ */
837
+ helper('pauseTest', pauseTest);
838
+
839
+
840
+ /**
841
+ Triggers the given DOM event on the element identified by the provided selector.
842
+
843
+ Example:
844
+
845
+ ```javascript
846
+ triggerEvent('#some-elem-id', 'blur');
847
+ ```
848
+
849
+ This is actually used internally by the `keyEvent` helper like so:
850
+
851
+ ```javascript
852
+ triggerEvent('#some-elem-id', 'keypress', { keyCode: 13 });
853
+ ```
854
+
855
+ @method triggerEvent
856
+ @param {String} selector jQuery selector for finding element on the DOM
857
+ @param {String} [context] jQuery selector that will limit the selector
858
+ argument to find only within the context's children
859
+ @param {String} type The event type to be triggered.
860
+ @param {Object} [options] The options to be passed to jQuery.Event.
861
+ @return {RSVP.Promise}
862
+ @since 1.5.0
863
+ */
864
+ asyncHelper('triggerEvent', triggerEvent);
865
+ });
866
+ enifed("ember-testing/initializers",
867
+ ["ember-runtime/system/lazy_load"],
868
+ function(__dependency1__) {
869
+ "use strict";
870
+ var onLoad = __dependency1__.onLoad;
871
+
872
+ var name = 'deferReadiness in `testing` mode';
873
+
874
+ onLoad('Ember.Application', function(Application) {
875
+ if (!Application.initializers[name]) {
876
+ Application.initializer({
877
+ name: name,
878
+
879
+ initialize: function(container, application){
880
+ if (application.testing) {
881
+ application.deferReadiness();
882
+ }
883
+ }
884
+ });
885
+ }
886
+ });
887
+ });
888
+ enifed("ember-testing/setup_for_testing",
889
+ ["ember-metal/core","ember-testing/adapters/qunit","ember-views/system/jquery","exports"],
890
+ function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
891
+ "use strict";
892
+ var Ember = __dependency1__["default"];
893
+ // import Test from "ember-testing/test"; // ES6TODO: fix when cycles are supported
894
+ var QUnitAdapter = __dependency2__["default"];
895
+ var jQuery = __dependency3__["default"];
896
+
897
+ var Test, requests;
898
+
899
+ function incrementAjaxPendingRequests(_, xhr){
900
+ requests.push(xhr);
901
+ Test.pendingAjaxRequests = requests.length;
902
+ }
903
+
904
+ function decrementAjaxPendingRequests(_, xhr){
905
+ for (var i=0;i<requests.length;i++) {
906
+ if (xhr === requests[i]) {
907
+ requests.splice(i, 1);
908
+ }
909
+ }
910
+ Test.pendingAjaxRequests = requests.length;
911
+ }
912
+
913
+ /**
914
+ Sets Ember up for testing. This is useful to perform
915
+ basic setup steps in order to unit test.
916
+
917
+ Use `App.setupForTesting` to perform integration tests (full
918
+ application testing).
919
+
920
+ @method setupForTesting
921
+ @namespace Ember
922
+ @since 1.5.0
923
+ */
924
+ __exports__["default"] = function setupForTesting() {
925
+ if (!Test) { Test = requireModule('ember-testing/test')['default']; }
926
+
927
+ Ember.testing = true;
928
+
929
+ // if adapter is not manually set default to QUnit
930
+ if (!Test.adapter) {
931
+ Test.adapter = QUnitAdapter.create();
932
+ }
933
+
934
+ requests = [];
935
+ Test.pendingAjaxRequests = requests.length;
936
+
937
+ jQuery(document).off('ajaxSend', incrementAjaxPendingRequests);
938
+ jQuery(document).off('ajaxComplete', decrementAjaxPendingRequests);
939
+ jQuery(document).on('ajaxSend', incrementAjaxPendingRequests);
940
+ jQuery(document).on('ajaxComplete', decrementAjaxPendingRequests);
941
+ }
942
+ });
943
+ enifed("ember-testing/support",
944
+ ["ember-metal/core","ember-views/system/jquery"],
945
+ function(__dependency1__, __dependency2__) {
946
+ "use strict";
947
+ var Ember = __dependency1__["default"];
948
+ var jQuery = __dependency2__["default"];
949
+
950
+ /**
951
+ @module ember
952
+ @submodule ember-testing
953
+ */
954
+
955
+ var $ = jQuery;
956
+
957
+ /**
958
+ This method creates a checkbox and triggers the click event to fire the
959
+ passed in handler. It is used to correct for a bug in older versions
960
+ of jQuery (e.g 1.8.3).
961
+
962
+ @private
963
+ @method testCheckboxClick
964
+ */
965
+ function testCheckboxClick(handler) {
966
+ $('<input type="checkbox">')
967
+ .css({ position: 'absolute', left: '-1000px', top: '-1000px' })
968
+ .appendTo('body')
969
+ .on('click', handler)
970
+ .trigger('click')
971
+ .remove();
972
+ }
973
+
974
+ $(function() {
975
+ /*
976
+ Determine whether a checkbox checked using jQuery's "click" method will have
977
+ the correct value for its checked property.
978
+
979
+ If we determine that the current jQuery version exhibits this behavior,
980
+ patch it to work correctly as in the commit for the actual fix:
981
+ https://github.com/jquery/jquery/commit/1fb2f92.
982
+ */
983
+ testCheckboxClick(function() {
984
+ if (!this.checked && !$.event.special.click) {
985
+ $.event.special.click = {
986
+ // For checkbox, fire native event so checked state will be right
987
+ trigger: function() {
988
+ if ($.nodeName( this, "input" ) && this.type === "checkbox" && this.click) {
989
+ this.click();
990
+ return false;
991
+ }
992
+ }
993
+ };
994
+ }
995
+ });
996
+
997
+ // Try again to verify that the patch took effect or blow up.
998
+ testCheckboxClick(function() {
999
+ Ember.warn("clicked checkboxes should be checked! the jQuery patch didn't work", this.checked);
1000
+ });
1001
+ });
1002
+ });
1003
+ enifed("ember-testing/test",
1004
+ ["ember-metal/core","ember-metal/run_loop","ember-metal/platform","ember-runtime/compare","ember-runtime/ext/rsvp","ember-testing/setup_for_testing","ember-application/system/application","exports"],
1005
+ function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
1006
+ "use strict";
1007
+ var Ember = __dependency1__["default"];
1008
+ var emberRun = __dependency2__["default"];
1009
+ var create = __dependency3__.create;
1010
+ var compare = __dependency4__["default"];
1011
+ var RSVP = __dependency5__["default"];
1012
+ var setupForTesting = __dependency6__["default"];
1013
+ var EmberApplication = __dependency7__["default"];
1014
+
1015
+ /**
1016
+ @module ember
1017
+ @submodule ember-testing
1018
+ */
1019
+ var slice = [].slice;
1020
+ var helpers = {};
1021
+ var injectHelpersCallbacks = [];
1022
+
1023
+ /**
1024
+ This is a container for an assortment of testing related functionality:
1025
+
1026
+ * Choose your default test adapter (for your framework of choice).
1027
+ * Register/Unregister additional test helpers.
1028
+ * Setup callbacks to be fired when the test helpers are injected into
1029
+ your application.
1030
+
1031
+ @class Test
1032
+ @namespace Ember
1033
+ */
1034
+ var Test = {
1035
+ /**
1036
+ Hash containing all known test helpers.
1037
+
1038
+ @property _helpers
1039
+ @private
1040
+ @since 1.7.0
1041
+ */
1042
+ _helpers: helpers,
1043
+
1044
+ /**
1045
+ `registerHelper` is used to register a test helper that will be injected
1046
+ when `App.injectTestHelpers` is called.
1047
+
1048
+ The helper method will always be called with the current Application as
1049
+ the first parameter.
1050
+
1051
+ For example:
1052
+
1053
+ ```javascript
1054
+ Ember.Test.registerHelper('boot', function(app) {
1055
+ Ember.run(app, app.advanceReadiness);
1056
+ });
1057
+ ```
1058
+
1059
+ This helper can later be called without arguments because it will be
1060
+ called with `app` as the first parameter.
1061
+
1062
+ ```javascript
1063
+ App = Ember.Application.create();
1064
+ App.injectTestHelpers();
1065
+ boot();
1066
+ ```
1067
+
1068
+ @public
1069
+ @method registerHelper
1070
+ @param {String} name The name of the helper method to add.
1071
+ @param {Function} helperMethod
1072
+ @param options {Object}
1073
+ */
1074
+ registerHelper: function(name, helperMethod) {
1075
+ helpers[name] = {
1076
+ method: helperMethod,
1077
+ meta: { wait: false }
1078
+ };
1079
+ },
1080
+
1081
+ /**
1082
+ `registerAsyncHelper` is used to register an async test helper that will be injected
1083
+ when `App.injectTestHelpers` is called.
1084
+
1085
+ The helper method will always be called with the current Application as
1086
+ the first parameter.
1087
+
1088
+ For example:
1089
+
1090
+ ```javascript
1091
+ Ember.Test.registerAsyncHelper('boot', function(app) {
1092
+ Ember.run(app, app.advanceReadiness);
1093
+ });
1094
+ ```
1095
+
1096
+ The advantage of an async helper is that it will not run
1097
+ until the last async helper has completed. All async helpers
1098
+ after it will wait for it complete before running.
1099
+
1100
+
1101
+ For example:
1102
+
1103
+ ```javascript
1104
+ Ember.Test.registerAsyncHelper('deletePost', function(app, postId) {
1105
+ click('.delete-' + postId);
1106
+ });
1107
+
1108
+ // ... in your test
1109
+ visit('/post/2');
1110
+ deletePost(2);
1111
+ visit('/post/3');
1112
+ deletePost(3);
1113
+ ```
1114
+
1115
+ @public
1116
+ @method registerAsyncHelper
1117
+ @param {String} name The name of the helper method to add.
1118
+ @param {Function} helperMethod
1119
+ @since 1.2.0
1120
+ */
1121
+ registerAsyncHelper: function(name, helperMethod) {
1122
+ helpers[name] = {
1123
+ method: helperMethod,
1124
+ meta: { wait: true }
1125
+ };
1126
+ },
1127
+
1128
+ /**
1129
+ Remove a previously added helper method.
1130
+
1131
+ Example:
1132
+
1133
+ ```javascript
1134
+ Ember.Test.unregisterHelper('wait');
1135
+ ```
1136
+
1137
+ @public
1138
+ @method unregisterHelper
1139
+ @param {String} name The helper to remove.
1140
+ */
1141
+ unregisterHelper: function(name) {
1142
+ delete helpers[name];
1143
+ delete Test.Promise.prototype[name];
1144
+ },
1145
+
1146
+ /**
1147
+ Used to register callbacks to be fired whenever `App.injectTestHelpers`
1148
+ is called.
1149
+
1150
+ The callback will receive the current application as an argument.
1151
+
1152
+ Example:
1153
+
1154
+ ```javascript
1155
+ Ember.Test.onInjectHelpers(function() {
1156
+ Ember.$(document).ajaxSend(function() {
1157
+ Test.pendingAjaxRequests++;
1158
+ });
1159
+
1160
+ Ember.$(document).ajaxComplete(function() {
1161
+ Test.pendingAjaxRequests--;
1162
+ });
1163
+ });
1164
+ ```
1165
+
1166
+ @public
1167
+ @method onInjectHelpers
1168
+ @param {Function} callback The function to be called.
1169
+ */
1170
+ onInjectHelpers: function(callback) {
1171
+ injectHelpersCallbacks.push(callback);
1172
+ },
1173
+
1174
+ /**
1175
+ This returns a thenable tailored for testing. It catches failed
1176
+ `onSuccess` callbacks and invokes the `Ember.Test.adapter.exception`
1177
+ callback in the last chained then.
1178
+
1179
+ This method should be returned by async helpers such as `wait`.
1180
+
1181
+ @public
1182
+ @method promise
1183
+ @param {Function} resolver The function used to resolve the promise.
1184
+ */
1185
+ promise: function(resolver) {
1186
+ return new Test.Promise(resolver);
1187
+ },
1188
+
1189
+ /**
1190
+ Used to allow ember-testing to communicate with a specific testing
1191
+ framework.
1192
+
1193
+ You can manually set it before calling `App.setupForTesting()`.
1194
+
1195
+ Example:
1196
+
1197
+ ```javascript
1198
+ Ember.Test.adapter = MyCustomAdapter.create()
1199
+ ```
1200
+
1201
+ If you do not set it, ember-testing will default to `Ember.Test.QUnitAdapter`.
1202
+
1203
+ @public
1204
+ @property adapter
1205
+ @type {Class} The adapter to be used.
1206
+ @default Ember.Test.QUnitAdapter
1207
+ */
1208
+ adapter: null,
1209
+
1210
+ /**
1211
+ Replacement for `Ember.RSVP.resolve`
1212
+ The only difference is this uses
1213
+ an instance of `Ember.Test.Promise`
1214
+
1215
+ @public
1216
+ @method resolve
1217
+ @param {Mixed} The value to resolve
1218
+ @since 1.2.0
1219
+ */
1220
+ resolve: function(val) {
1221
+ return Test.promise(function(resolve) {
1222
+ return resolve(val);
1223
+ });
1224
+ },
1225
+
1226
+ /**
1227
+ This allows ember-testing to play nicely with other asynchronous
1228
+ events, such as an application that is waiting for a CSS3
1229
+ transition or an IndexDB transaction.
1230
+
1231
+ For example:
1232
+
1233
+ ```javascript
1234
+ Ember.Test.registerWaiter(function() {
1235
+ return myPendingTransactions() == 0;
1236
+ });
1237
+ ```
1238
+ The `context` argument allows you to optionally specify the `this`
1239
+ with which your callback will be invoked.
1240
+
1241
+ For example:
1242
+
1243
+ ```javascript
1244
+ Ember.Test.registerWaiter(MyDB, MyDB.hasPendingTransactions);
1245
+ ```
1246
+
1247
+ @public
1248
+ @method registerWaiter
1249
+ @param {Object} context (optional)
1250
+ @param {Function} callback
1251
+ @since 1.2.0
1252
+ */
1253
+ registerWaiter: function(context, callback) {
1254
+ if (arguments.length === 1) {
1255
+ callback = context;
1256
+ context = null;
1257
+ }
1258
+ if (!this.waiters) {
1259
+ this.waiters = Ember.A();
1260
+ }
1261
+ this.waiters.push([context, callback]);
1262
+ },
1263
+ /**
1264
+ `unregisterWaiter` is used to unregister a callback that was
1265
+ registered with `registerWaiter`.
1266
+
1267
+ @public
1268
+ @method unregisterWaiter
1269
+ @param {Object} context (optional)
1270
+ @param {Function} callback
1271
+ @since 1.2.0
1272
+ */
1273
+ unregisterWaiter: function(context, callback) {
1274
+ var pair;
1275
+ if (!this.waiters) { return; }
1276
+ if (arguments.length === 1) {
1277
+ callback = context;
1278
+ context = null;
1279
+ }
1280
+ pair = [context, callback];
1281
+ this.waiters = Ember.A(this.waiters.filter(function(elt) {
1282
+ return compare(elt, pair)!==0;
1283
+ }));
1284
+ }
1285
+ };
1286
+
1287
+ function helper(app, name) {
1288
+ var fn = helpers[name].method;
1289
+ var meta = helpers[name].meta;
1290
+
1291
+ return function() {
1292
+ var args = slice.call(arguments);
1293
+ var lastPromise = Test.lastPromise;
1294
+
1295
+ args.unshift(app);
1296
+
1297
+ // some helpers are not async and
1298
+ // need to return a value immediately.
1299
+ // example: `find`
1300
+ if (!meta.wait) {
1301
+ return fn.apply(app, args);
1302
+ }
1303
+
1304
+ if (!lastPromise) {
1305
+ // It's the first async helper in current context
1306
+ lastPromise = fn.apply(app, args);
1307
+ } else {
1308
+ // wait for last helper's promise to resolve
1309
+ // and then execute
1310
+ run(function() {
1311
+ lastPromise = Test.resolve(lastPromise).then(function() {
1312
+ return fn.apply(app, args);
1313
+ });
1314
+ });
1315
+ }
1316
+
1317
+ return lastPromise;
1318
+ };
1319
+ }
1320
+
1321
+ function run(fn) {
1322
+ if (!emberRun.currentRunLoop) {
1323
+ emberRun(fn);
1324
+ } else {
1325
+ fn();
1326
+ }
1327
+ }
1328
+
1329
+ EmberApplication.reopen({
1330
+ /**
1331
+ This property contains the testing helpers for the current application. These
1332
+ are created once you call `injectTestHelpers` on your `Ember.Application`
1333
+ instance. The included helpers are also available on the `window` object by
1334
+ default, but can be used from this object on the individual application also.
1335
+
1336
+ @property testHelpers
1337
+ @type {Object}
1338
+ @default {}
1339
+ */
1340
+ testHelpers: {},
1341
+
1342
+ /**
1343
+ This property will contain the original methods that were registered
1344
+ on the `helperContainer` before `injectTestHelpers` is called.
1345
+
1346
+ When `removeTestHelpers` is called, these methods are restored to the
1347
+ `helperContainer`.
1348
+
1349
+ @property originalMethods
1350
+ @type {Object}
1351
+ @default {}
1352
+ @private
1353
+ @since 1.3.0
1354
+ */
1355
+ originalMethods: {},
1356
+
1357
+
1358
+ /**
1359
+ This property indicates whether or not this application is currently in
1360
+ testing mode. This is set when `setupForTesting` is called on the current
1361
+ application.
1362
+
1363
+ @property testing
1364
+ @type {Boolean}
1365
+ @default false
1366
+ @since 1.3.0
1367
+ */
1368
+ testing: false,
1369
+
1370
+ /**
1371
+ This hook defers the readiness of the application, so that you can start
1372
+ the app when your tests are ready to run. It also sets the router's
1373
+ location to 'none', so that the window's location will not be modified
1374
+ (preventing both accidental leaking of state between tests and interference
1375
+ with your testing framework).
1376
+
1377
+ Example:
1378
+
1379
+ ```
1380
+ App.setupForTesting();
1381
+ ```
1382
+
1383
+ @method setupForTesting
1384
+ */
1385
+ setupForTesting: function() {
1386
+ setupForTesting();
1387
+
1388
+ this.testing = true;
1389
+
1390
+ this.Router.reopen({
1391
+ location: 'none'
1392
+ });
1393
+ },
1394
+
1395
+ /**
1396
+ This will be used as the container to inject the test helpers into. By
1397
+ default the helpers are injected into `window`.
1398
+
1399
+ @property helperContainer
1400
+ @type {Object} The object to be used for test helpers.
1401
+ @default window
1402
+ @since 1.2.0
1403
+ */
1404
+ helperContainer: window,
1405
+
1406
+ /**
1407
+ This injects the test helpers into the `helperContainer` object. If an object is provided
1408
+ it will be used as the helperContainer. If `helperContainer` is not set it will default
1409
+ to `window`. If a function of the same name has already been defined it will be cached
1410
+ (so that it can be reset if the helper is removed with `unregisterHelper` or
1411
+ `removeTestHelpers`).
1412
+
1413
+ Any callbacks registered with `onInjectHelpers` will be called once the
1414
+ helpers have been injected.
1415
+
1416
+ Example:
1417
+ ```
1418
+ App.injectTestHelpers();
1419
+ ```
1420
+
1421
+ @method injectTestHelpers
1422
+ */
1423
+ injectTestHelpers: function(helperContainer) {
1424
+ if (helperContainer) { this.helperContainer = helperContainer; }
1425
+
1426
+ this.testHelpers = {};
1427
+ for (var name in helpers) {
1428
+ this.originalMethods[name] = this.helperContainer[name];
1429
+ this.testHelpers[name] = this.helperContainer[name] = helper(this, name);
1430
+ protoWrap(Test.Promise.prototype, name, helper(this, name), helpers[name].meta.wait);
1431
+ }
1432
+
1433
+ for(var i = 0, l = injectHelpersCallbacks.length; i < l; i++) {
1434
+ injectHelpersCallbacks[i](this);
1435
+ }
1436
+ },
1437
+
1438
+ /**
1439
+ This removes all helpers that have been registered, and resets and functions
1440
+ that were overridden by the helpers.
1441
+
1442
+ Example:
1443
+
1444
+ ```javascript
1445
+ App.removeTestHelpers();
1446
+ ```
1447
+
1448
+ @public
1449
+ @method removeTestHelpers
1450
+ */
1451
+ removeTestHelpers: function() {
1452
+ for (var name in helpers) {
1453
+ this.helperContainer[name] = this.originalMethods[name];
1454
+ delete this.testHelpers[name];
1455
+ delete this.originalMethods[name];
1456
+ }
1457
+ }
1458
+ });
1459
+
1460
+ // This method is no longer needed
1461
+ // But still here for backwards compatibility
1462
+ // of helper chaining
1463
+ function protoWrap(proto, name, callback, isAsync) {
1464
+ proto[name] = function() {
1465
+ var args = arguments;
1466
+ if (isAsync) {
1467
+ return callback.apply(this, args);
1468
+ } else {
1469
+ return this.then(function() {
1470
+ return callback.apply(this, args);
1471
+ });
1472
+ }
1473
+ };
1474
+ }
1475
+
1476
+ Test.Promise = function() {
1477
+ RSVP.Promise.apply(this, arguments);
1478
+ Test.lastPromise = this;
1479
+ };
1480
+
1481
+ Test.Promise.prototype = create(RSVP.Promise.prototype);
1482
+ Test.Promise.prototype.constructor = Test.Promise;
1483
+
1484
+ // Patch `then` to isolate async methods
1485
+ // specifically `Ember.Test.lastPromise`
1486
+ var originalThen = RSVP.Promise.prototype.then;
1487
+ Test.Promise.prototype.then = function(onSuccess, onFailure) {
1488
+ return originalThen.call(this, function(val) {
1489
+ return isolate(onSuccess, val);
1490
+ }, onFailure);
1491
+ };
1492
+
1493
+ // This method isolates nested async methods
1494
+ // so that they don't conflict with other last promises.
1495
+ //
1496
+ // 1. Set `Ember.Test.lastPromise` to null
1497
+ // 2. Invoke method
1498
+ // 3. Return the last promise created during method
1499
+ // 4. Restore `Ember.Test.lastPromise` to original value
1500
+ function isolate(fn, val) {
1501
+ var value, lastPromise;
1502
+
1503
+ // Reset lastPromise for nested helpers
1504
+ Test.lastPromise = null;
1505
+
1506
+ value = fn(val);
1507
+
1508
+ lastPromise = Test.lastPromise;
1509
+
1510
+ // If the method returned a promise
1511
+ // return that promise. If not,
1512
+ // return the last async helper's promise
1513
+ if ((value && (value instanceof Test.Promise)) || !lastPromise) {
1514
+ return value;
1515
+ } else {
1516
+ run(function() {
1517
+ lastPromise = Test.resolve(lastPromise).then(function() {
1518
+ return value;
1519
+ });
1520
+ });
1521
+ return lastPromise;
1522
+ }
1523
+ }
1524
+
1525
+ __exports__["default"] = Test;
1526
+ });
1527
+ requireModule("ember-testing");
1528
+
1529
+ })();