UNPKG

jest-jasmine2

Version:
1,429 lines (1,409 loc) 43.9 kB
import { AssertionError } from "assert"; import { ErrorWithStack, convertDescriptorToString, formatTime, isPromise } from "jest-util"; import chalk from "chalk"; import { diff, printExpected, printReceived } from "jest-matcher-utils"; import { format } from "pretty-format"; //#region src/assertionErrorMessage.ts const assertOperatorsMap = { "!=": "notEqual", "!==": "notStrictEqual", "==": "equal", "===": "strictEqual" }; const humanReadableOperators = { deepEqual: "to deeply equal", deepStrictEqual: "to deeply and strictly equal", equal: "to be equal", notDeepEqual: "not to deeply equal", notDeepStrictEqual: "not to deeply and strictly equal", notEqual: "to not be equal", notStrictEqual: "not be strictly equal", strictEqual: "to strictly be equal" }; const getOperatorName = (operator, stack) => { if (typeof operator === "string") return assertOperatorsMap[operator] || operator; if (stack.match(".doesNotThrow")) return "doesNotThrow"; if (stack.match(".throws")) return "throws"; return ""; }; const operatorMessage = (operator) => { const niceOperatorName = getOperatorName(operator, ""); const humanReadableOperator = humanReadableOperators[niceOperatorName]; return typeof operator === "string" ? `${humanReadableOperator || niceOperatorName} to:\n` : ""; }; const assertThrowingMatcherHint = (operatorName) => operatorName ? chalk.dim("assert") + chalk.dim(`.${operatorName}(`) + chalk.red("function") + chalk.dim(")") : ""; const assertMatcherHint = (operator, operatorName, expected) => { let message = ""; if (operator === "==" && expected === true) message = chalk.dim("assert") + chalk.dim("(") + chalk.red("received") + chalk.dim(")"); else if (operatorName) message = chalk.dim("assert") + chalk.dim(`.${operatorName}(`) + chalk.red("received") + chalk.dim(", ") + chalk.green("expected") + chalk.dim(")"); return message; }; function assertionErrorMessage(error, options) { const { expected, actual, generatedMessage, message, operator, stack } = error; const diffString = diff(expected, actual, options); const hasCustomMessage = !generatedMessage; const operatorName = getOperatorName(operator, stack); const trimmedStack = stack.replace(message, "").replaceAll(/AssertionError(.*)/g, ""); if (operatorName === "doesNotThrow") return `${buildHintString(assertThrowingMatcherHint(operatorName)) + chalk.reset("Expected the function not to throw an error.\n") + chalk.reset("Instead, it threw:\n")} ${printReceived(actual)}${chalk.reset(hasCustomMessage ? `\n\nMessage:\n ${message}` : "")}${trimmedStack}`; if (operatorName === "throws") { if (error.generatedMessage) return buildHintString(assertThrowingMatcherHint(operatorName)) + chalk.reset(error.message) + chalk.reset(hasCustomMessage ? `\n\nMessage:\n ${message}` : "") + trimmedStack; return buildHintString(assertThrowingMatcherHint(operatorName)) + chalk.reset("Expected the function to throw an error.\n") + chalk.reset("But it didn't throw anything.") + chalk.reset(hasCustomMessage ? `\n\nMessage:\n ${message}` : "") + trimmedStack; } if (operatorName === "fail") return buildHintString(assertMatcherHint(operator, operatorName, expected)) + chalk.reset(hasCustomMessage ? `Message:\n ${message}` : "") + trimmedStack; return `${buildHintString(assertMatcherHint(operator, operatorName, expected)) + chalk.reset(`Expected value ${operatorMessage(operator)}`)} ${printExpected(expected)}\n${chalk.reset("Received:\n")} ${printReceived(actual)}${chalk.reset(hasCustomMessage ? `\n\nMessage:\n ${message}` : "")}${diffString ? `\n\nDifference:\n\n${diffString}` : ""}${trimmedStack}`; } function buildHintString(hint) { return hint ? `${hint}\n\n` : ""; } var assertionErrorMessage_default = assertionErrorMessage; //#endregion //#region src/isError.ts function isError(potentialError) { const isError$1 = potentialError !== null && typeof potentialError === "object" && typeof potentialError.message === "string" && typeof potentialError.name === "string"; const message = isError$1 ? null : `Failed: ${format(potentialError, { maxDepth: 3 })}`; return { isError: isError$1, message }; } //#endregion //#region src/PCancelable.ts /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var CancelError = class extends Error { constructor() { super("Promise was canceled"); this.name = "CancelError"; } }; var PCancelable = class { _pending = true; _canceled = false; _promise; _cancel; _reject = () => {}; constructor(executor) { this._promise = new Promise((resolve, reject) => { this._reject = reject; return executor((fn) => { this._cancel = fn; }, (val) => { this._pending = false; resolve(val); }, (err) => { this._pending = false; reject(err); }); }); } then(onFulfilled, onRejected) { return this._promise.then(onFulfilled, onRejected); } catch(onRejected) { return this._promise.catch(onRejected); } cancel() { if (!this._pending || this._canceled) return; if (typeof this._cancel === "function") try { this._cancel(); } catch (error) { this._reject(error); } this._canceled = true; this._reject(new CancelError()); } }; //#endregion //#region src/pTimeout.ts /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ function pTimeout(promise, ms, clearTimeout$1, setTimeout$1, onTimeout) { return new Promise((resolve, reject) => { const timer = setTimeout$1(() => resolve(onTimeout()), ms); promise.then((val) => { clearTimeout$1(timer); resolve(val); }, (error) => { clearTimeout$1(timer); reject(error); }); }); } //#endregion //#region src/queueRunner.ts function queueRunner(options) { const token = new PCancelable((onCancel, resolve) => { onCancel(resolve); }); const mapper = ({ fn, timeout, initError = new Error() }) => { let promise = new Promise((resolve) => { const next = function(...args) { const err = args[0]; if (err) options.fail.apply(null, args); resolve(); }; next.fail = function(...args) { options.fail.apply(null, args); resolve(); }; try { fn.call(options.userContext, next); } catch (error) { options.onException(error); resolve(); } }); promise = Promise.race([promise, token]); if (!timeout) return promise; const timeoutMs = timeout(); return pTimeout(promise, timeoutMs, options.clearTimeout, options.setTimeout, () => { initError.message = `Timeout - Async callback was not invoked within the ${formatTime(timeoutMs)} timeout specified by jest.setTimeout.`; initError.stack = initError.message + initError.stack; options.onException(initError); }); }; const result = options.queueableFns.reduce((promise, fn) => promise.then(() => mapper(fn)), Promise.resolve()); return { cancel: token.cancel.bind(token), catch: result.catch.bind(result), then: result.then.bind(result) }; } //#endregion //#region src/treeProcessor.ts const noop = () => {}; function getNodeWithoutChildrenHandler(node, enabled) { return function fn(done = noop) { node.execute(done, enabled); }; } function hasNoEnabledTest(node) { return node.disabled || node.markedPending || (node.children?.every(hasNoEnabledTest) ?? false); } function treeProcessor(options) { const { nodeComplete, nodeStart, queueRunnerFactory, runnableIds, tree } = options; function isEnabled(node, parentEnabled) { return parentEnabled || runnableIds.includes(node.id); } function getNodeHandler(node, parentEnabled) { const enabled = isEnabled(node, parentEnabled); return node.children ? getNodeWithChildrenHandler(node, enabled) : getNodeWithoutChildrenHandler(node, enabled); } function getNodeWithChildrenHandler(node, enabled) { return async function fn(done = noop) { nodeStart(node); await queueRunnerFactory({ onException: (error) => node.onException(error), queueableFns: wrapChildren(node, enabled), userContext: node.sharedUserContext() }); nodeComplete(node); done(); }; } function wrapChildren(node, enabled) { if (!node.children) throw new Error("`node.children` is not defined."); const children = node.children.map((child) => ({ fn: getNodeHandler(child, enabled) })); if (hasNoEnabledTest(node)) return children; return [ ...node.beforeAllFns, ...children, ...node.afterAllFns ]; } const treeHandler = getNodeHandler(tree, false); return treeHandler(); } //#endregion //#region src/jasmine/Env.ts function jasmineEnv(j$) { return class Env { specFilter; catchExceptions; throwOnExpectationFailure; catchingExceptions; topSuite; fail; pending; afterAll; fit; throwingExpectationFailures; randomizeTests; randomTests; seed; execute; fdescribe; spyOn; beforeEach; afterEach; clearReporters; addReporter; it; xdescribe; xit; beforeAll; todo; provideFallbackReporter; allowRespy; describe; constructor() { let totalSpecsDefined = 0; let catchExceptions = true; const realSetTimeout = globalThis.setTimeout; const realClearTimeout = globalThis.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.at(-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 queueRunner(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() { oldListenersException = [...process.listeners("uncaughtException")]; oldListenersRejection = [...process.listeners("unhandledRejection")]; 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); for (const listener of oldListenersException) j$.process.on("uncaughtException", listener); for (const listener of oldListenersRejection) j$.process.on("unhandledRejection", listener); }; this.execute = async function(runnablesToRun, suiteTree = topSuite) { if (!runnablesToRun) if (focusedRunnables.length > 0) runnablesToRun = focusedRunnables; else runnablesToRun = [suiteTree.id]; if (currentlyExecutingSuites.length === 0) executionSetup(); const lastDeclarationSuite = currentDeclarationSuite; await treeProcessor({ 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 === void 0) throw new Error("Missing second argument. It must be a callback function."); if (typeof specDefinitions !== "function") throw new TypeError(`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) 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 = void 0; let describeReturnValue; try { describeReturnValue = specDefinitions.call(suite); } catch (error) { declarationError = error; } if (isPromise(describeReturnValue)) declarationError = new Error("Returning a Promise from \"describe\" is not supported. Tests must be defined synchronously."); else if (describeReturnValue !== void 0) 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$1) { return getSpecName(spec$1, 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$1) { currentSpec = spec$1; defaultResourcesForRunnable(spec$1.id, suite.id); reporter.specStarted(spec$1.result); } }; this.it = function(description, fn, timeout) { description = convertDescriptorToString(description); if (fn === void 0) 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 TypeError(`Invalid second argument, ${fn}. It must be a callback function.`); const spec = specFactory(description, fn, currentDeclarationSuite, timeout); if (currentDeclarationSuite.markedPending) spec.pend(); 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 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 AssertionError || error && error.name === AssertionError.name) { checkIsError = false; message = assertionErrorMessage_default(error, { expand: j$.Spec.expand }); } else { const check = isError(error); checkIsError = check.isError; message = check.message || void 0; } 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 }); }; } }; } //#endregion //#region src/jasmine/JsApiReporter.ts const noopTimer = { start() {}, elapsed() { return 0; } }; var JsApiReporter = class { started; finished; runDetails; jasmineStarted; jasmineDone; status; executionTime; suiteStarted; suiteDone; suiteResults; suites; specResults; specDone; specs; specStarted; constructor(options) { const timer = options.timer || noopTimer; let status = "loaded"; this.started = false; this.finished = false; this.runDetails = {}; this.jasmineStarted = () => { this.started = true; status = "started"; timer.start(); }; let executionTime; function validateAfterAllExceptions({ failedExpectations }) { if (failedExpectations && failedExpectations.length > 0) throw failedExpectations[0]; } this.jasmineDone = function(runDetails) { validateAfterAllExceptions(runDetails); this.finished = true; this.runDetails = runDetails; executionTime = timer.elapsed(); status = "done"; }; this.status = function() { return status; }; const suites = []; const suites_hash = {}; this.specStarted = function() {}; this.suiteStarted = function(result) { suites_hash[result.id] = result; }; this.suiteDone = function(result) { storeSuite(result); }; this.suiteResults = function(index, length) { return suites.slice(index, index + length); }; function storeSuite(result) { suites.push(result); suites_hash[result.id] = result; } this.suites = function() { return suites_hash; }; const specs = []; this.specDone = function(result) { specs.push(result); }; this.specResults = function(index, length) { return specs.slice(index, index + length); }; this.specs = function() { return specs; }; this.executionTime = function() { return executionTime; }; } }; //#endregion //#region src/jasmine/ReportDispatcher.ts var ReportDispatcher = class { addReporter; provideFallbackReporter; clearReporters; jasmineDone; jasmineStarted; specDone; specStarted; suiteDone; suiteStarted; constructor(methods) { const dispatchedMethods = methods || []; for (const method of dispatchedMethods) this[method] = function(m) { return function() { dispatch(m, arguments); }; }(method); let reporters = []; let fallbackReporter = null; this.addReporter = function(reporter) { reporters.push(reporter); }; this.provideFallbackReporter = function(reporter) { fallbackReporter = reporter; }; this.clearReporters = function() { reporters = []; }; return this; function dispatch(method, args) { if (reporters.length === 0 && fallbackReporter !== null) reporters.push(fallbackReporter); for (const reporter of reporters) if (reporter[method]) reporter[method].apply(reporter, args); } } }; //#endregion //#region src/ExpectationFailed.ts /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var ExpectationFailed = class extends Error {}; //#endregion //#region src/expectationResultFactory.ts function messageFormatter({ error, message, passed }) { if (passed) return "Passed."; if (message) return message; if (typeof error === "string") return error; if (error && typeof error === "object" && typeof error.message === "string" && typeof error.name === "string") { if (error.message === "") return error.name; return `${error.name}: ${error.message}`; } return `thrown: ${format(error, { maxDepth: 3 })}`; } function stackFormatter(options, initError, errorMessage) { if (options.passed) return ""; if (options.error) { if (typeof options.error.stack === "string") return options.error.stack; if (options.error === errorMessage) return errorMessage; } if (initError) return `${errorMessage.trimEnd()}\n\n${initError.stack}`; return new Error(errorMessage).stack; } function expectationResultFactory(options, initError) { const message = messageFormatter(options); const stack = stackFormatter(options, initError, message); if (options.passed) return { error: options.error, matcherName: options.matcherName, message, passed: options.passed, stack }; return { actual: options.actual, error: options.error, expected: options.expected, matcherName: options.matcherName, message, passed: options.passed, stack }; } //#endregion //#region src/jasmine/Spec.ts var Spec = class Spec { id; description; resultCallback; queueableFn; beforeAndAfterFns; userContext; onStart; getSpecName; queueRunnerFactory; throwOnExpectationFailure; initError; result; disabled; currentRun; markedTodo; markedPending; expand; static pendingSpecExceptionMessage; static isPendingSpecException(e) { return !!(e && e.toString && e.toString().includes(Spec.pendingSpecExceptionMessage)); } constructor(attrs) { this.resultCallback = attrs.resultCallback || function() {}; this.id = attrs.id; this.description = convertDescriptorToString(attrs.description); this.queueableFn = attrs.queueableFn; this.beforeAndAfterFns = attrs.beforeAndAfterFns || function() { return { befores: [], afters: [] }; }; this.userContext = attrs.userContext || function() { return {}; }; this.onStart = attrs.onStart || function() {}; this.getSpecName = attrs.getSpecName || function() { return ""; }; this.queueRunnerFactory = attrs.queueRunnerFactory || function() {}; this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure; this.initError = new Error(); this.initError.name = ""; this.initError.stack = this.initError.stack; this.queueableFn.initError = this.initError; this.result = { id: this.id, description: this.description, fullName: this.getFullName(), failedExpectations: [], passedExpectations: [], pendingReason: "", testPath: attrs.getTestPath() }; } addExpectationResult(passed, data, isError$1) { const expectationResult = expectationResultFactory(data, this.initError); if (passed) this.result.passedExpectations.push(expectationResult); else { this.result.failedExpectations.push(expectationResult); if (this.throwOnExpectationFailure && !isError$1) throw new ExpectationFailed(); } } execute(onComplete, enabled) { const self = this; this.onStart(this); if (!this.isExecutable() || this.markedPending || this.markedTodo || enabled === false) { complete(enabled); return; } const fns = this.beforeAndAfterFns(); const allFns = fns.befores.concat(this.queueableFn).concat(fns.afters); this.currentRun = this.queueRunnerFactory({ queueableFns: allFns, onException() { self.onException.apply(self, arguments); }, userContext: this.userContext(), setTimeout, clearTimeout, fail: () => {} }); this.currentRun.then(() => complete(true)); function complete(enabledAgain) { self.result.status = self.status(enabledAgain); self.resultCallback(self.result); if (onComplete) onComplete(); } } cancel() { if (this.currentRun) this.currentRun.cancel(); } onException(error) { if (Spec.isPendingSpecException(error)) { this.pend(extractCustomPendingMessage(error)); return; } if (error instanceof ExpectationFailed) return; this.addExpectationResult(false, { matcherName: "", passed: false, expected: "", actual: "", error: this.isAssertionError(error) ? assertionErrorMessage_default(error, { expand: this.expand }) : error }, true); } disable() { this.disabled = true; } pend(message) { this.markedPending = true; if (message) this.result.pendingReason = message; } todo() { this.markedTodo = true; } getResult() { this.result.status = this.status(); return this.result; } status(enabled) { if (this.disabled || enabled === false) return "disabled"; if (this.markedTodo) return "todo"; if (this.markedPending) return "pending"; if (this.result.failedExpectations.length > 0) return "failed"; else return "passed"; } isExecutable() { return !this.disabled; } getFullName() { return this.getSpecName(this); } isAssertionError(error) { return error instanceof AssertionError || error && error.name === AssertionError.name; } }; Spec.pendingSpecExceptionMessage = "=> marked Pending"; const extractCustomPendingMessage = function(e) { const fullMessage = e.toString(); const boilerplateStart = fullMessage.indexOf(Spec.pendingSpecExceptionMessage); const boilerplateEnd = boilerplateStart + Spec.pendingSpecExceptionMessage.length; return fullMessage.slice(boilerplateEnd); }; //#endregion //#region src/jasmine/Suite.ts var Suite = class { id; parentSuite; description; throwOnExpectationFailure; beforeFns; afterFns; beforeAllFns; afterAllFns; disabled; children; result; sharedContext; markedPending; markedTodo; isFocused; constructor(attrs) { this.markedPending = false; this.markedTodo = false; this.isFocused = false; this.id = attrs.id; this.parentSuite = attrs.parentSuite; this.description = convertDescriptorToString(attrs.description); this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure; this.beforeFns = []; this.afterFns = []; this.beforeAllFns = []; this.afterAllFns = []; this.disabled = false; this.children = []; this.result = { id: this.id, description: this.description, fullName: this.getFullName(), failedExpectations: [], testPath: attrs.getTestPath() }; } getFullName() { const fullName = []; for (let parentSuite = this; parentSuite; parentSuite = parentSuite.parentSuite) if (parentSuite.parentSuite) fullName.unshift(parentSuite.description); return fullName.join(" "); } disable() { this.disabled = true; } pend(_message) { this.markedPending = true; } beforeEach(fn) { this.beforeFns.unshift(fn); } beforeAll(fn) { this.beforeAllFns.push(fn); } afterEach(fn) { this.afterFns.unshift(fn); } afterAll(fn) { this.afterAllFns.unshift(fn); } addChild(child) { this.children.push(child); } status() { if (this.disabled) return "disabled"; if (this.markedPending) return "pending"; if (this.result.failedExpectations.length > 0) return "failed"; else return "finished"; } isExecutable() { return !this.disabled; } canBeReentered() { return this.beforeAllFns.length === 0 && this.afterAllFns.length === 0; } getResult() { this.result.status = this.status(); return this.result; } sharedUserContext() { if (!this.sharedContext) this.sharedContext = {}; return this.sharedContext; } clonedSharedUserContext() { return this.sharedUserContext(); } onException(...args) { if (args[0] instanceof ExpectationFailed) return; if (isAfterAll(this.children)) { const data = { matcherName: "", passed: false, expected: "", actual: "", error: arguments[0] }; this.result.failedExpectations.push(expectationResultFactory(data)); } else for (const child of this.children) child.onException.apply(child, args); } addExpectationResult(...args) { if (isAfterAll(this.children) && isFailure(args)) { const data = args[1]; this.result.failedExpectations.push(expectationResultFactory(data)); if (this.throwOnExpectationFailure) throw new ExpectationFailed(); } else for (const child of this.children) try { child.addExpectationResult.apply(child, args); } catch {} } execute(..._args) {} }; function isAfterAll(children) { return children && children[0] && children[0].result.status; } function isFailure(args) { return !args[0]; } //#endregion //#region src/jasmine/Timer.ts /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * */ const defaultNow = function(Date$1) { return function() { return Date$1.now(); }; }(Date); var Timer = class { start; elapsed; constructor(options) { options = options || {}; const now = options.now || defaultNow; let startTime; this.start = function() { startTime = now(); }; this.elapsed = function() { return now() - startTime; }; } }; //#endregion //#region src/jasmine/CallTracker.ts var CallTracker = class { track; any; count; argsFor; all; allArgs; first; mostRecent; reset; constructor() { let calls = []; this.track = function(context) { calls.push(context); }; this.any = function() { return calls.length > 0; }; this.count = function() { return calls.length; }; this.argsFor = function(index) { const call = calls[index]; return call ? call.args : []; }; this.all = function() { return calls; }; this.allArgs = function() { const callArgs = []; for (const call of calls) callArgs.push(call.args); return callArgs; }; this.first = function() { return calls[0]; }; this.mostRecent = function() { return calls.at(-1); }; this.reset = function() { calls = []; }; } }; var CallTracker_default = CallTracker; //#endregion //#region src/jasmine/SpyStrategy.ts /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * */ var SpyStrategy = class { identity; exec; callThrough; returnValue; returnValues; throwError; callFake; stub; constructor({ name = "unknown", fn = function() {}, getSpy = function() {} } = {}) { const identity = name; const originalFn = fn; let plan = function() {}; this.identity = function() { return identity; }; this.exec = function() { return plan.apply(this, arguments); }; this.callThrough = function() { plan = originalFn; return getSpy(); }; this.returnValue = function(value) { plan = function() { return value; }; return getSpy(); }; this.returnValues = function() { const values = Array.prototype.slice.call(arguments); plan = function() { return values.shift(); }; return getSpy(); }; this.throwError = function(something) { const error = something instanceof Error ? something : new Error(something); plan = function() { throw error; }; return getSpy(); }; this.callFake = function(fn$1) { if (typeof fn$1 !== "function") throw new TypeError(`Argument passed to callFake should be a function, got ${fn$1}`); plan = fn$1; return getSpy(); }; this.stub = function(_fn) { plan = function() {}; return getSpy(); }; } }; //#endregion //#region src/jasmine/createSpy.ts function createSpy(name, originalFn) { const spyStrategy = new SpyStrategy({ name, fn: originalFn, getSpy() { return spy; } }); const callTracker = new CallTracker_default(); const spy = function(...args) { const callData = { object: this, args: Array.prototype.slice.apply(arguments) }; callTracker.track(callData); const returnValue = spyStrategy.exec.apply(this, args); callData.returnValue = returnValue; return returnValue; }; for (const prop in originalFn) { if (prop === "and" || prop === "calls") throw new Error("Jasmine spies would overwrite the 'and' and 'calls' properties on the object being spied upon"); spy[prop] = originalFn[prop]; } spy.and = spyStrategy; spy.calls = callTracker; return spy; } var createSpy_default = createSpy; //#endregion //#region src/jasmine/spyRegistry.ts const formatErrorMsg = (domain, usage) => { const usageDefinition = usage ? `\nUsage: ${usage}` : ""; return (msg) => `${domain} : ${msg}${usageDefinition}`; }; function isSpy(putativeSpy) { if (!putativeSpy) return false; return putativeSpy.and instanceof SpyStrategy && putativeSpy.calls instanceof CallTracker_default; } const getErrorMsg = formatErrorMsg("<spyOn>", "spyOn(<object>, <methodName>)"); var SpyRegistry = class { allowRespy; spyOn; clearSpies; respy; _spyOnProperty; constructor({ currentSpies = () => [] } = {}) { this.allowRespy = function(allow) { this.respy = allow; }; this.spyOn = (obj, methodName, accessType) => { if (accessType) return this._spyOnProperty(obj, methodName, accessType); if (obj === void 0) throw new Error(getErrorMsg(`could not find an object to spy upon for ${methodName}()`)); if (methodName === void 0) throw new Error(getErrorMsg("No method name supplied")); if (obj[methodName] === void 0) throw new Error(getErrorMsg(`${methodName}() method does not exist`)); if (obj[methodName] && isSpy(obj[methodName])) if (this.respy) return obj[methodName]; else throw new Error(getErrorMsg(`${methodName} has already been spied upon`)); let descriptor; try { descriptor = Object.getOwnPropertyDescriptor(obj, methodName); } catch {} if (descriptor && !(descriptor.writable || descriptor.set)) throw new Error(getErrorMsg(`${methodName} is not declared writable or has no setter`)); const originalMethod = obj[methodName]; const spiedMethod = createSpy_default(methodName, originalMethod); let restoreStrategy; if (Object.prototype.hasOwnProperty.call(obj, methodName)) restoreStrategy = function() { obj[methodName] = originalMethod; }; else restoreStrategy = function() { if (!delete obj[methodName]) obj[methodName] = originalMethod; }; currentSpies().push({ restoreObjectToOriginalState: restoreStrategy }); obj[methodName] = spiedMethod; return spiedMethod; }; this._spyOnProperty = function(obj, propertyName, accessType = "get") { if (!obj) throw new Error(getErrorMsg(`could not find an object to spy upon for ${propertyName}`)); if (!propertyName) throw new Error(getErrorMsg("No property name supplied")); let descriptor; try { descriptor = Object.getOwnPropertyDescriptor(obj, propertyName); } catch {} if (!descriptor) throw new Error(getErrorMsg(`${propertyName} property does not exist`)); if (!descriptor.configurable) throw new Error(getErrorMsg(`${propertyName} is not declared configurable`)); if (!descriptor[accessType]) throw new Error(getErrorMsg(`Property ${propertyName} does not have access type ${accessType}`)); if (obj[propertyName] && isSpy(obj[propertyName])) if (this.respy) return obj[propertyName]; else throw new Error(getErrorMsg(`${propertyName} has already been spied upon`)); const originalDescriptor = descriptor; const spiedProperty = createSpy_default(propertyName, descriptor[accessType]); let restoreStrategy; if (Object.prototype.hasOwnProperty.call(obj, propertyName)) restoreStrategy = function() { Object.defineProperty(obj, propertyName, originalDescriptor); }; else restoreStrategy = function() { delete obj[propertyName]; }; currentSpies().push({ restoreObjectToOriginalState: restoreStrategy }); const spiedDescriptor = { ...descriptor, [accessType]: spiedProperty }; Object.defineProperty(obj, propertyName, spiedDescriptor); return spiedProperty; }; this.clearSpies = function() { const spies = currentSpies(); for (let i = spies.length - 1; i >= 0; i--) { const spyEntry = spies[i]; spyEntry.restoreObjectToOriginalState(); } }; } }; //#endregion //#region src/jasmine/jasmineLight.ts const testTimeoutSymbol = Symbol.for("TEST_TIMEOUT_SYMBOL"); const create = function(createOptions) { const j$ = { ...createOptions }; Object.defineProperty(j$, "_DEFAULT_TIMEOUT_INTERVAL", { configurable: true, enumerable: true, get() { return globalThis[testTimeoutSymbol] || createOptions.testTimeout || 5e3; }, set(value) { globalThis[testTimeoutSymbol] = value; } }); j$.getEnv = function() { const env = j$.currentEnv_ = j$.currentEnv_ || new j$.Env(); return env; }; j$.createSpy = createSpy_default; j$.Env = jasmineEnv(j$); j$.JsApiReporter = JsApiReporter; j$.ReportDispatcher = ReportDispatcher; j$.Spec = Spec; j$.SpyRegistry = SpyRegistry; j$.Suite = Suite; j$.Timer = Timer; j$.version = "2.5.2-light"; return j$; }; const _interface = function(jasmine, env) { const jasmineInterface = { describe(description, specDefinitions) { return env.describe(description, specDefinitions); }, xdescribe(description, specDefinitions) { return env.xdescribe(description, specDefinitions); }, fdescribe(description, specDefinitions) { return env.fdescribe(description, specDefinitions); }, it() { return env.it.apply(env, arguments); }, xit() { return env.xit.apply(env, arguments); }, fit() { return env.fit.apply(env, arguments); }, beforeEach() { if (typeof arguments[0] !== "function") throw new TypeError("Invalid first argument. It must be a callback function."); return env.beforeEach.apply(env, arguments); }, afterEach() { if (typeof arguments[0] !== "function") throw new TypeError("Invalid first argument. It must be a callback function."); return env.afterEach.apply(env, arguments); }, beforeAll() { if (typeof arguments[0] !== "function") throw new TypeError("Invalid first argument. It must be a callback function."); return env.beforeAll.apply(env, arguments); }, afterAll() { if (typeof arguments[0] !== "function") throw new TypeError("Invalid first argument. It must be a callback function."); return env.afterAll.apply(env, arguments); }, pending() { return env.pending.apply(env, arguments); }, fail() { return env.fail.apply(env, arguments); }, spyOn(obj, methodName, accessType) { return env.spyOn(obj, methodName, accessType); }, jsApiReporter: new jasmine.JsApiReporter({ timer: new jasmine.Timer() }), jasmine }; return jasmineInterface; }; //#endregion export { _interface, create };