| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716 | 'use strict';Object.defineProperty(exports, '__esModule', {  value: true});exports.default = jasmineEnv;var _assert = require('assert');var _jestUtil = require('jest-util');var _assertionErrorMessage = _interopRequireDefault(  require('../assertionErrorMessage'));var _isError = _interopRequireDefault(require('../isError'));var _queueRunner = _interopRequireDefault(require('../queueRunner'));var _treeProcessor = _interopRequireDefault(require('../treeProcessor'));function _interopRequireDefault(obj) {  return obj && obj.__esModule ? obj : {default: obj};}function _defineProperty(obj, key, value) {  if (key in obj) {    Object.defineProperty(obj, key, {      value: value,      enumerable: true,      configurable: true,      writable: true    });  } else {    obj[key] = value;  }  return obj;}function jasmineEnv(j$) {  return class Env {    constructor() {      _defineProperty(this, 'specFilter', void 0);      _defineProperty(this, 'catchExceptions', void 0);      _defineProperty(this, 'throwOnExpectationFailure', void 0);      _defineProperty(this, 'catchingExceptions', void 0);      _defineProperty(this, 'topSuite', void 0);      _defineProperty(this, 'fail', void 0);      _defineProperty(this, 'pending', void 0);      _defineProperty(this, 'afterAll', void 0);      _defineProperty(this, 'fit', void 0);      _defineProperty(this, 'throwingExpectationFailures', void 0);      _defineProperty(this, 'randomizeTests', void 0);      _defineProperty(this, 'randomTests', void 0);      _defineProperty(this, 'seed', void 0);      _defineProperty(this, 'execute', void 0);      _defineProperty(this, 'fdescribe', void 0);      _defineProperty(this, 'spyOn', void 0);      _defineProperty(this, 'beforeEach', void 0);      _defineProperty(this, 'afterEach', void 0);      _defineProperty(this, 'clearReporters', void 0);      _defineProperty(this, 'addReporter', void 0);      _defineProperty(this, 'it', void 0);      _defineProperty(this, 'xdescribe', void 0);      _defineProperty(this, 'xit', void 0);      _defineProperty(this, 'beforeAll', void 0);      _defineProperty(this, 'todo', void 0);      _defineProperty(this, 'provideFallbackReporter', void 0);      _defineProperty(this, 'allowRespy', void 0);      _defineProperty(this, 'describe', void 0);      let totalSpecsDefined = 0;      let catchExceptions = true;      const realSetTimeout = global.setTimeout;      const realClearTimeout = global.clearTimeout;      const runnableResources = {};      const currentlyExecutingSuites = [];      let currentSpec = null;      let throwOnExpectationFailure = false;      let random = false;      let seed = null;      let nextSpecId = 0;      let nextSuiteId = 0;      const getNextSpecId = function () {        return 'spec' + nextSpecId++;      };      const getNextSuiteId = function () {        return 'suite' + nextSuiteId++;      };      const topSuite = new j$.Suite({        id: getNextSuiteId(),        description: '',        getTestPath() {          return j$.testPath;        }      });      let currentDeclarationSuite = topSuite;      const currentSuite = function () {        return currentlyExecutingSuites[currentlyExecutingSuites.length - 1];      };      const currentRunnable = function () {        return currentSpec || currentSuite();      };      const reporter = new j$.ReportDispatcher([        'jasmineStarted',        'jasmineDone',        'suiteStarted',        'suiteDone',        'specStarted',        'specDone'      ]);      this.specFilter = function () {        return true;      };      const defaultResourcesForRunnable = function (id, _parentRunnableId) {        const resources = {          spies: []        };        runnableResources[id] = resources;      };      const clearResourcesForRunnable = function (id) {        spyRegistry.clearSpies();        delete runnableResources[id];      };      const beforeAndAfterFns = function (suite) {        return function () {          let afters = [];          let befores = [];          while (suite) {            befores = befores.concat(suite.beforeFns);            afters = afters.concat(suite.afterFns);            suite = suite.parentSuite;          }          return {            befores: befores.reverse(),            afters          };        };      };      const getSpecName = function (spec, suite) {        const fullName = [spec.description];        const suiteFullName = suite.getFullName();        if (suiteFullName !== '') {          fullName.unshift(suiteFullName);        }        return fullName.join(' ');      };      this.catchExceptions = function (value) {        catchExceptions = !!value;        return catchExceptions;      };      this.catchingExceptions = function () {        return catchExceptions;      };      this.throwOnExpectationFailure = function (value) {        throwOnExpectationFailure = !!value;      };      this.throwingExpectationFailures = function () {        return throwOnExpectationFailure;      };      this.randomizeTests = function (value) {        random = !!value;      };      this.randomTests = function () {        return random;      };      this.seed = function (value) {        if (value) {          seed = value;        }        return seed;      };      const queueRunnerFactory = options => {        options.clearTimeout = realClearTimeout;        options.fail = this.fail;        options.setTimeout = realSetTimeout;        return (0, _queueRunner.default)(options);      };      this.topSuite = function () {        return topSuite;      };      const uncaught = err => {        if (currentSpec) {          currentSpec.onException(err);          currentSpec.cancel();        } else {          console.error('Unhandled error');          console.error(err.stack);        }      };      let oldListenersException;      let oldListenersRejection;      const executionSetup = function () {        // Need to ensure we are the only ones handling these exceptions.        oldListenersException = process.listeners('uncaughtException').slice();        oldListenersRejection = process.listeners('unhandledRejection').slice();        j$.process.removeAllListeners('uncaughtException');        j$.process.removeAllListeners('unhandledRejection');        j$.process.on('uncaughtException', uncaught);        j$.process.on('unhandledRejection', uncaught);      };      const executionTeardown = function () {        j$.process.removeListener('uncaughtException', uncaught);        j$.process.removeListener('unhandledRejection', uncaught); // restore previous exception handlers        oldListenersException.forEach(listener => {          j$.process.on('uncaughtException', listener);        });        oldListenersRejection.forEach(listener => {          j$.process.on('unhandledRejection', listener);        });      };      this.execute = async function (runnablesToRun, suiteTree = topSuite) {        if (!runnablesToRun) {          if (focusedRunnables.length) {            runnablesToRun = focusedRunnables;          } else {            runnablesToRun = [suiteTree.id];          }        }        if (currentlyExecutingSuites.length === 0) {          executionSetup();        }        const lastDeclarationSuite = currentDeclarationSuite;        await (0, _treeProcessor.default)({          nodeComplete(suite) {            if (!suite.disabled) {              clearResourcesForRunnable(suite.id);            }            currentlyExecutingSuites.pop();            if (suite === topSuite) {              reporter.jasmineDone({                failedExpectations: topSuite.result.failedExpectations              });            } else {              reporter.suiteDone(suite.getResult());            }          },          nodeStart(suite) {            currentlyExecutingSuites.push(suite);            defaultResourcesForRunnable(              suite.id,              suite.parentSuite && suite.parentSuite.id            );            if (suite === topSuite) {              reporter.jasmineStarted({                totalSpecsDefined              });            } else {              reporter.suiteStarted(suite.result);            }          },          queueRunnerFactory,          runnableIds: runnablesToRun,          tree: suiteTree        });        currentDeclarationSuite = lastDeclarationSuite;        if (currentlyExecutingSuites.length === 0) {          executionTeardown();        }      };      this.addReporter = function (reporterToAdd) {        reporter.addReporter(reporterToAdd);      };      this.provideFallbackReporter = function (reporterToAdd) {        reporter.provideFallbackReporter(reporterToAdd);      };      this.clearReporters = function () {        reporter.clearReporters();      };      const spyRegistry = new j$.SpyRegistry({        currentSpies() {          if (!currentRunnable()) {            throw new Error(              'Spies must be created in a before function or a spec'            );          }          return runnableResources[currentRunnable().id].spies;        }      });      this.allowRespy = function (allow) {        spyRegistry.allowRespy(allow);      };      this.spyOn = function (...args) {        return spyRegistry.spyOn.apply(spyRegistry, args);      };      const suiteFactory = function (description) {        const suite = new j$.Suite({          id: getNextSuiteId(),          description,          parentSuite: currentDeclarationSuite,          throwOnExpectationFailure,          getTestPath() {            return j$.testPath;          }        });        return suite;      };      this.describe = function (description, specDefinitions) {        const suite = suiteFactory(description);        if (specDefinitions === undefined) {          throw new Error(            'Missing second argument. It must be a callback function.'          );        }        if (typeof specDefinitions !== 'function') {          throw new Error(            `Invalid second argument, ${specDefinitions}. It must be a callback function.`          );        }        if (specDefinitions.length > 0) {          throw new Error('describe does not expect any arguments');        }        if (currentDeclarationSuite.markedPending) {          suite.pend();        }        if (currentDeclarationSuite.markedTodo) {          // @ts-expect-error TODO Possible error: Suite does not have todo method          suite.todo();        }        addSpecsToSuite(suite, specDefinitions);        return suite;      };      this.xdescribe = function (description, specDefinitions) {        const suite = suiteFactory(description);        suite.pend();        addSpecsToSuite(suite, specDefinitions);        return suite;      };      const focusedRunnables = [];      this.fdescribe = function (description, specDefinitions) {        const suite = suiteFactory(description);        suite.isFocused = true;        focusedRunnables.push(suite.id);        unfocusAncestor();        addSpecsToSuite(suite, specDefinitions);        return suite;      };      const addSpecsToSuite = (suite, specDefinitions) => {        const parentSuite = currentDeclarationSuite;        parentSuite.addChild(suite);        currentDeclarationSuite = suite;        let declarationError = undefined;        let describeReturnValue;        try {          describeReturnValue = specDefinitions.call(suite);        } catch (e) {          declarationError = e;        }        if ((0, _jestUtil.isPromise)(describeReturnValue)) {          declarationError = new Error(            'Returning a Promise from "describe" is not supported. Tests must be defined synchronously.'          );        } else if (describeReturnValue !== undefined) {          declarationError = new Error(            'A "describe" callback must not return a value.'          );        }        if (declarationError) {          this.it('encountered a declaration exception', () => {            throw declarationError;          });        }        currentDeclarationSuite = parentSuite;      };      function findFocusedAncestor(suite) {        while (suite) {          if (suite.isFocused) {            return suite.id;          }          suite = suite.parentSuite;        }        return null;      }      function unfocusAncestor() {        const focusedAncestor = findFocusedAncestor(currentDeclarationSuite);        if (focusedAncestor) {          for (let i = 0; i < focusedRunnables.length; i++) {            if (focusedRunnables[i] === focusedAncestor) {              focusedRunnables.splice(i, 1);              break;            }          }        }      }      const specFactory = (description, fn, suite, timeout) => {        totalSpecsDefined++;        const spec = new j$.Spec({          id: getNextSpecId(),          beforeAndAfterFns: beforeAndAfterFns(suite),          resultCallback: specResultCallback,          getSpecName(spec) {            return getSpecName(spec, suite);          },          getTestPath() {            return j$.testPath;          },          onStart: specStarted,          description,          queueRunnerFactory,          userContext() {            return suite.clonedSharedUserContext();          },          queueableFn: {            fn,            timeout() {              return timeout || j$._DEFAULT_TIMEOUT_INTERVAL;            }          },          throwOnExpectationFailure        });        if (!this.specFilter(spec)) {          spec.disable();        }        return spec;        function specResultCallback(result) {          clearResourcesForRunnable(spec.id);          currentSpec = null;          reporter.specDone(result);        }        function specStarted(spec) {          currentSpec = spec;          defaultResourcesForRunnable(spec.id, suite.id);          reporter.specStarted(spec.result);        }      };      this.it = function (description, fn, timeout) {        if (typeof description !== 'string') {          throw new Error(            `Invalid first argument, ${description}. It must be a string.`          );        }        if (fn === undefined) {          throw new Error(            'Missing second argument. It must be a callback function. Perhaps you want to use `test.todo` for a test placeholder.'          );        }        if (typeof fn !== 'function') {          throw new Error(            `Invalid second argument, ${fn}. It must be a callback function.`          );        }        const spec = specFactory(          description,          fn,          currentDeclarationSuite,          timeout        );        if (currentDeclarationSuite.markedPending) {          spec.pend();        } // When a test is defined inside another, jasmine will not run it.        // This check throws an error to warn the user about the edge-case.        if (currentSpec !== null) {          throw new Error(            `Tests cannot be nested. Test "${spec.description}" cannot run because it is nested within "${currentSpec.description}".`          );        }        currentDeclarationSuite.addChild(spec);        return spec;      };      this.xit = function (...args) {        const spec = this.it.apply(this, args);        spec.pend('Temporarily disabled with xit');        return spec;      };      this.todo = function () {        const description = arguments[0];        if (arguments.length !== 1 || typeof description !== 'string') {          throw new _jestUtil.ErrorWithStack(            'Todo must be called with only a description.',            this.todo          );        }        const spec = specFactory(          description,          () => {},          currentDeclarationSuite        );        if (currentDeclarationSuite.markedPending) {          spec.pend();        } else {          spec.todo();        }        currentDeclarationSuite.addChild(spec);        return spec;      };      this.fit = function (description, fn, timeout) {        const spec = specFactory(          description,          fn,          currentDeclarationSuite,          timeout        );        currentDeclarationSuite.addChild(spec);        if (currentDeclarationSuite.markedPending) {          spec.pend();        } else {          focusedRunnables.push(spec.id);        }        unfocusAncestor();        return spec;      };      this.beforeEach = function (beforeEachFunction, timeout) {        currentDeclarationSuite.beforeEach({          fn: beforeEachFunction,          timeout() {            return timeout || j$._DEFAULT_TIMEOUT_INTERVAL;          }        });      };      this.beforeAll = function (beforeAllFunction, timeout) {        currentDeclarationSuite.beforeAll({          fn: beforeAllFunction,          timeout() {            return timeout || j$._DEFAULT_TIMEOUT_INTERVAL;          }        });      };      this.afterEach = function (afterEachFunction, timeout) {        currentDeclarationSuite.afterEach({          fn: afterEachFunction,          timeout() {            return timeout || j$._DEFAULT_TIMEOUT_INTERVAL;          }        });      };      this.afterAll = function (afterAllFunction, timeout) {        currentDeclarationSuite.afterAll({          fn: afterAllFunction,          timeout() {            return timeout || j$._DEFAULT_TIMEOUT_INTERVAL;          }        });      };      this.pending = function (message) {        let fullMessage = j$.Spec.pendingSpecExceptionMessage;        if (message) {          fullMessage += message;        }        throw fullMessage;      };      this.fail = function (error) {        let checkIsError;        let message;        if (          error instanceof _assert.AssertionError ||          (error && error.name === _assert.AssertionError.name)        ) {          checkIsError = false; // @ts-expect-error TODO Possible error: j$.Spec does not have expand property          message = (0, _assertionErrorMessage.default)(error, {            expand: j$.Spec.expand          });        } else {          const check = (0, _isError.default)(error);          checkIsError = check.isError;          message = check.message;        }        const errorAsErrorObject = checkIsError ? error : new Error(message);        const runnable = currentRunnable();        if (!runnable) {          errorAsErrorObject.message =            'Caught error after test environment was torn down\n\n' +            errorAsErrorObject.message;          throw errorAsErrorObject;        }        runnable.addExpectationResult(false, {          matcherName: '',          passed: false,          expected: '',          actual: '',          message,          error: errorAsErrorObject        });      };    }  };}
 |