jasmineAsyncInstall.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', {
  3. value: true
  4. });
  5. exports.default = jasmineAsyncInstall;
  6. var _co = _interopRequireDefault(require('co'));
  7. var _isGeneratorFn = _interopRequireDefault(require('is-generator-fn'));
  8. var _throat = _interopRequireDefault(require('throat'));
  9. var _isError3 = _interopRequireDefault(require('./isError'));
  10. function _interopRequireDefault(obj) {
  11. return obj && obj.__esModule ? obj : {default: obj};
  12. }
  13. var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
  14. var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
  15. var Promise = global[Symbol.for('jest-native-promise')] || global.Promise;
  16. function isPromise(obj) {
  17. return obj && typeof obj.then === 'function';
  18. }
  19. function promisifyLifeCycleFunction(originalFn, env) {
  20. return function(fn, timeout) {
  21. if (!fn) {
  22. return originalFn.call(env);
  23. }
  24. const hasDoneCallback = typeof fn === 'function' && fn.length > 0;
  25. if (hasDoneCallback) {
  26. // Jasmine will handle it
  27. return originalFn.call(env, fn, timeout);
  28. }
  29. const extraError = new Error(); // Without this line v8 stores references to all closures
  30. // in the stack in the Error object. This line stringifies the stack
  31. // property to allow garbage-collecting objects on the stack
  32. // https://crbug.com/v8/7142
  33. extraError.stack = extraError.stack; // We make *all* functions async and run `done` right away if they
  34. // didn't return a promise.
  35. const asyncJestLifecycle = function asyncJestLifecycle(done) {
  36. const wrappedFn = (0, _isGeneratorFn.default)(fn)
  37. ? _co.default.wrap(fn)
  38. : fn;
  39. const returnValue = wrappedFn.call({});
  40. if (isPromise(returnValue)) {
  41. returnValue.then(done.bind(null, null), error => {
  42. const _isError = (0, _isError3.default)(error),
  43. checkIsError = _isError.isError,
  44. message = _isError.message;
  45. if (message) {
  46. extraError.message = message;
  47. }
  48. done.fail(checkIsError ? error : extraError);
  49. });
  50. } else {
  51. done();
  52. }
  53. };
  54. return originalFn.call(env, asyncJestLifecycle, timeout);
  55. };
  56. } // Similar to promisifyLifeCycleFunction but throws an error
  57. // when the return value is neither a Promise nor `undefined`
  58. function promisifyIt(originalFn, env, jasmine) {
  59. return function(specName, fn, timeout) {
  60. if (!fn) {
  61. const spec = originalFn.call(env, specName);
  62. spec.pend('not implemented');
  63. return spec;
  64. }
  65. const hasDoneCallback = fn.length > 0;
  66. if (hasDoneCallback) {
  67. return originalFn.call(env, specName, fn, timeout);
  68. }
  69. const extraError = new Error(); // Without this line v8 stores references to all closures
  70. // in the stack in the Error object. This line stringifies the stack
  71. // property to allow garbage-collecting objects on the stack
  72. // https://crbug.com/v8/7142
  73. extraError.stack = extraError.stack;
  74. const asyncJestTest = function asyncJestTest(done) {
  75. const wrappedFn = (0, _isGeneratorFn.default)(fn)
  76. ? _co.default.wrap(fn)
  77. : fn;
  78. const returnValue = wrappedFn.call({});
  79. if (isPromise(returnValue)) {
  80. returnValue.then(done.bind(null, null), error => {
  81. const _isError2 = (0, _isError3.default)(error),
  82. checkIsError = _isError2.isError,
  83. message = _isError2.message;
  84. if (message) {
  85. extraError.message = message;
  86. }
  87. if (jasmine.Spec.isPendingSpecException(error)) {
  88. env.pending(message);
  89. done();
  90. } else {
  91. done.fail(checkIsError ? error : extraError);
  92. }
  93. });
  94. } else if (returnValue === undefined) {
  95. done();
  96. } else {
  97. done.fail(
  98. new Error(
  99. 'Jest: `it` and `test` must return either a Promise or undefined.'
  100. )
  101. );
  102. }
  103. };
  104. return originalFn.call(env, specName, asyncJestTest, timeout);
  105. };
  106. }
  107. function makeConcurrent(originalFn, env, mutex) {
  108. return function(specName, fn, timeout) {
  109. if (
  110. env != null &&
  111. !env.specFilter({
  112. getFullName: () => specName || ''
  113. })
  114. ) {
  115. return originalFn.call(env, specName, () => Promise.resolve(), timeout);
  116. }
  117. let promise;
  118. try {
  119. promise = mutex(() => {
  120. const promise = fn();
  121. if (isPromise(promise)) {
  122. return promise;
  123. }
  124. throw new Error(
  125. `Jest: concurrent test "${specName}" must return a Promise.`
  126. );
  127. });
  128. } catch (error) {
  129. return originalFn.call(env, specName, () => Promise.reject(error));
  130. }
  131. return originalFn.call(env, specName, () => promise, timeout);
  132. };
  133. }
  134. function jasmineAsyncInstall(globalConfig, global) {
  135. const jasmine = global.jasmine;
  136. const mutex = (0, _throat.default)(globalConfig.maxConcurrency);
  137. const env = jasmine.getEnv();
  138. env.it = promisifyIt(env.it, env, jasmine);
  139. env.fit = promisifyIt(env.fit, env, jasmine);
  140. global.it.concurrent = (env => {
  141. const concurrent = makeConcurrent(env.it, env, mutex);
  142. concurrent.only = makeConcurrent(env.fit, env, mutex);
  143. concurrent.skip = makeConcurrent(env.xit, env, mutex);
  144. return concurrent;
  145. })(env);
  146. global.fit.concurrent = makeConcurrent(env.fit, env, mutex);
  147. env.afterAll = promisifyLifeCycleFunction(env.afterAll, env);
  148. env.afterEach = promisifyLifeCycleFunction(env.afterEach, env);
  149. env.beforeAll = promisifyLifeCycleFunction(env.beforeAll, env);
  150. env.beforeEach = promisifyLifeCycleFunction(env.beforeEach, env);
  151. }