Spec.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. var _assert = require('assert');
  7. var _ExpectationFailed = _interopRequireDefault(
  8. require('../ExpectationFailed')
  9. );
  10. var _assertionErrorMessage = _interopRequireDefault(
  11. require('../assertionErrorMessage')
  12. );
  13. var _expectationResultFactory = _interopRequireDefault(
  14. require('../expectationResultFactory')
  15. );
  16. function _interopRequireDefault(obj) {
  17. return obj && obj.__esModule ? obj : {default: obj};
  18. }
  19. function _defineProperty(obj, key, value) {
  20. if (key in obj) {
  21. Object.defineProperty(obj, key, {
  22. value: value,
  23. enumerable: true,
  24. configurable: true,
  25. writable: true
  26. });
  27. } else {
  28. obj[key] = value;
  29. }
  30. return obj;
  31. }
  32. class Spec {
  33. static isPendingSpecException(e) {
  34. return !!(
  35. e &&
  36. e.toString &&
  37. e.toString().indexOf(Spec.pendingSpecExceptionMessage) !== -1
  38. );
  39. }
  40. constructor(attrs) {
  41. _defineProperty(this, 'id', void 0);
  42. _defineProperty(this, 'description', void 0);
  43. _defineProperty(this, 'resultCallback', void 0);
  44. _defineProperty(this, 'queueableFn', void 0);
  45. _defineProperty(this, 'beforeAndAfterFns', void 0);
  46. _defineProperty(this, 'userContext', void 0);
  47. _defineProperty(this, 'onStart', void 0);
  48. _defineProperty(this, 'getSpecName', void 0);
  49. _defineProperty(this, 'queueRunnerFactory', void 0);
  50. _defineProperty(this, 'throwOnExpectationFailure', void 0);
  51. _defineProperty(this, 'initError', void 0);
  52. _defineProperty(this, 'result', void 0);
  53. _defineProperty(this, 'disabled', void 0);
  54. _defineProperty(this, 'currentRun', void 0);
  55. _defineProperty(this, 'markedTodo', void 0);
  56. _defineProperty(this, 'markedPending', void 0);
  57. _defineProperty(this, 'expand', void 0);
  58. this.resultCallback = attrs.resultCallback || function () {};
  59. this.id = attrs.id;
  60. this.description = attrs.description || '';
  61. this.queueableFn = attrs.queueableFn;
  62. this.beforeAndAfterFns =
  63. attrs.beforeAndAfterFns ||
  64. function () {
  65. return {
  66. befores: [],
  67. afters: []
  68. };
  69. };
  70. this.userContext =
  71. attrs.userContext ||
  72. function () {
  73. return {};
  74. };
  75. this.onStart = attrs.onStart || function () {};
  76. this.getSpecName =
  77. attrs.getSpecName ||
  78. function () {
  79. return '';
  80. };
  81. this.queueRunnerFactory = attrs.queueRunnerFactory || function () {};
  82. this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure;
  83. this.initError = new Error();
  84. this.initError.name = ''; // Without this line v8 stores references to all closures
  85. // in the stack in the Error object. This line stringifies the stack
  86. // property to allow garbage-collecting objects on the stack
  87. // https://crbug.com/v8/7142
  88. this.initError.stack = this.initError.stack;
  89. this.queueableFn.initError = this.initError; // @ts-expect-error
  90. this.result = {
  91. id: this.id,
  92. description: this.description,
  93. fullName: this.getFullName(),
  94. failedExpectations: [],
  95. passedExpectations: [],
  96. pendingReason: '',
  97. testPath: attrs.getTestPath()
  98. };
  99. }
  100. addExpectationResult(passed, data, isError) {
  101. const expectationResult = (0, _expectationResultFactory.default)(
  102. data,
  103. this.initError
  104. );
  105. if (passed) {
  106. this.result.passedExpectations.push(expectationResult);
  107. } else {
  108. this.result.failedExpectations.push(expectationResult);
  109. if (this.throwOnExpectationFailure && !isError) {
  110. throw new _ExpectationFailed.default();
  111. }
  112. }
  113. }
  114. execute(onComplete, enabled) {
  115. const self = this;
  116. this.onStart(this);
  117. if (
  118. !this.isExecutable() ||
  119. this.markedPending ||
  120. this.markedTodo ||
  121. enabled === false
  122. ) {
  123. complete(enabled);
  124. return;
  125. }
  126. const fns = this.beforeAndAfterFns();
  127. const allFns = fns.befores.concat(this.queueableFn).concat(fns.afters);
  128. this.currentRun = this.queueRunnerFactory({
  129. queueableFns: allFns,
  130. onException() {
  131. // @ts-expect-error
  132. self.onException.apply(self, arguments);
  133. },
  134. userContext: this.userContext(),
  135. setTimeout,
  136. clearTimeout,
  137. fail: () => {}
  138. });
  139. this.currentRun.then(() => complete(true));
  140. function complete(enabledAgain) {
  141. self.result.status = self.status(enabledAgain);
  142. self.resultCallback(self.result);
  143. if (onComplete) {
  144. onComplete();
  145. }
  146. }
  147. }
  148. cancel() {
  149. if (this.currentRun) {
  150. this.currentRun.cancel();
  151. }
  152. }
  153. onException(error) {
  154. if (Spec.isPendingSpecException(error)) {
  155. this.pend(extractCustomPendingMessage(error));
  156. return;
  157. }
  158. if (error instanceof _ExpectationFailed.default) {
  159. return;
  160. }
  161. this.addExpectationResult(
  162. false,
  163. {
  164. matcherName: '',
  165. passed: false,
  166. expected: '',
  167. actual: '',
  168. error: this.isAssertionError(error)
  169. ? (0, _assertionErrorMessage.default)(error, {
  170. expand: this.expand
  171. })
  172. : error
  173. },
  174. true
  175. );
  176. }
  177. disable() {
  178. this.disabled = true;
  179. }
  180. pend(message) {
  181. this.markedPending = true;
  182. if (message) {
  183. this.result.pendingReason = message;
  184. }
  185. }
  186. todo() {
  187. this.markedTodo = true;
  188. }
  189. getResult() {
  190. this.result.status = this.status();
  191. return this.result;
  192. }
  193. status(enabled) {
  194. if (this.disabled || enabled === false) {
  195. return 'disabled';
  196. }
  197. if (this.markedTodo) {
  198. return 'todo';
  199. }
  200. if (this.markedPending) {
  201. return 'pending';
  202. }
  203. if (this.result.failedExpectations.length > 0) {
  204. return 'failed';
  205. } else {
  206. return 'passed';
  207. }
  208. }
  209. isExecutable() {
  210. return !this.disabled;
  211. }
  212. getFullName() {
  213. return this.getSpecName(this);
  214. }
  215. isAssertionError(error) {
  216. return (
  217. error instanceof _assert.AssertionError ||
  218. (error && error.name === _assert.AssertionError.name)
  219. );
  220. }
  221. }
  222. exports.default = Spec;
  223. _defineProperty(Spec, 'pendingSpecExceptionMessage', void 0);
  224. Spec.pendingSpecExceptionMessage = '=> marked Pending';
  225. const extractCustomPendingMessage = function (e) {
  226. const fullMessage = e.toString();
  227. const boilerplateStart = fullMessage.indexOf(
  228. Spec.pendingSpecExceptionMessage
  229. );
  230. const boilerplateEnd =
  231. boilerplateStart + Spec.pendingSpecExceptionMessage.length;
  232. return fullMessage.substr(boilerplateEnd);
  233. };