async-testing.ts 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. /**
  2. * @license
  3. * Copyright Google Inc. All Rights Reserved.
  4. *
  5. * Use of this source code is governed by an MIT-style license that can be
  6. * found in the LICENSE file at https://angular.io/license
  7. */
  8. import '../zone-spec/async-test';
  9. Zone.__load_patch('asynctest', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
  10. /**
  11. * Wraps a test function in an asynchronous test zone. The test will automatically
  12. * complete when all asynchronous calls within this zone are done.
  13. */
  14. (Zone as any)[api.symbol('asyncTest')] = function asyncTest(fn: Function): (done: any) => any {
  15. // If we're running using the Jasmine test framework, adapt to call the 'done'
  16. // function when asynchronous activity is finished.
  17. if (global.jasmine) {
  18. // Not using an arrow function to preserve context passed from call site
  19. return function(done: any) {
  20. if (!done) {
  21. // if we run beforeEach in @angular/core/testing/testing_internal then we get no done
  22. // fake it here and assume sync.
  23. done = function() {};
  24. done.fail = function(e: any) {
  25. throw e;
  26. };
  27. }
  28. runInTestZone(fn, this, done, (err: any) => {
  29. if (typeof err === 'string') {
  30. return done.fail(new Error(<string>err));
  31. } else {
  32. done.fail(err);
  33. }
  34. });
  35. };
  36. }
  37. // Otherwise, return a promise which will resolve when asynchronous activity
  38. // is finished. This will be correctly consumed by the Mocha framework with
  39. // it('...', async(myFn)); or can be used in a custom framework.
  40. // Not using an arrow function to preserve context passed from call site
  41. return function() {
  42. return new Promise<void>((finishCallback, failCallback) => {
  43. runInTestZone(fn, this, finishCallback, failCallback);
  44. });
  45. };
  46. };
  47. function runInTestZone(
  48. fn: Function, context: any, finishCallback: Function, failCallback: Function) {
  49. const currentZone = Zone.current;
  50. const AsyncTestZoneSpec = (Zone as any)['AsyncTestZoneSpec'];
  51. if (AsyncTestZoneSpec === undefined) {
  52. throw new Error(
  53. 'AsyncTestZoneSpec is needed for the async() test helper but could not be found. ' +
  54. 'Please make sure that your environment includes zone.js/dist/async-test.js');
  55. }
  56. const ProxyZoneSpec = (Zone as any)['ProxyZoneSpec'] as {
  57. get(): {setDelegate(spec: ZoneSpec): void; getDelegate(): ZoneSpec;};
  58. assertPresent: () => void;
  59. };
  60. if (ProxyZoneSpec === undefined) {
  61. throw new Error(
  62. 'ProxyZoneSpec is needed for the async() test helper but could not be found. ' +
  63. 'Please make sure that your environment includes zone.js/dist/proxy.js');
  64. }
  65. const proxyZoneSpec = ProxyZoneSpec.get();
  66. ProxyZoneSpec.assertPresent();
  67. // We need to create the AsyncTestZoneSpec outside the ProxyZone.
  68. // If we do it in ProxyZone then we will get to infinite recursion.
  69. const proxyZone = Zone.current.getZoneWith('ProxyZoneSpec');
  70. const previousDelegate = proxyZoneSpec.getDelegate();
  71. proxyZone!.parent!.run(() => {
  72. const testZoneSpec: ZoneSpec = new AsyncTestZoneSpec(
  73. () => {
  74. // Need to restore the original zone.
  75. if (proxyZoneSpec.getDelegate() == testZoneSpec) {
  76. // Only reset the zone spec if it's
  77. // sill this one. Otherwise, assume
  78. // it's OK.
  79. proxyZoneSpec.setDelegate(previousDelegate);
  80. }
  81. (testZoneSpec as any).unPatchPromiseForTest();
  82. currentZone.run(() => {
  83. finishCallback();
  84. });
  85. },
  86. (error: any) => {
  87. // Need to restore the original zone.
  88. if (proxyZoneSpec.getDelegate() == testZoneSpec) {
  89. // Only reset the zone spec if it's sill this one. Otherwise, assume it's OK.
  90. proxyZoneSpec.setDelegate(previousDelegate);
  91. }
  92. (testZoneSpec as any).unPatchPromiseForTest();
  93. currentZone.run(() => {
  94. failCallback(error);
  95. });
  96. },
  97. 'test');
  98. proxyZoneSpec.setDelegate(testZoneSpec);
  99. (testZoneSpec as any).patchPromiseForTest();
  100. });
  101. return Zone.current.runGuarded(fn, context);
  102. }
  103. });