UNPKG

hm-react-cli

Version:

Create a Huimei React project by module

157 lines (140 loc) 6.01 kB
"use strict"; const chalk = require("chalk"); if (process.env.REACT_CLASS_EQUIVALENCE_TEST) { // Inside the class equivalence tester, we have a custom environment, let's // require that instead. require("./spec-equivalence-reporter/setupTests.js"); } else { const env = jasmine.getEnv(); const errorMap = require("./codes.json"); // TODO: Stop using spyOn in all the test since that seem deprecated. // This is a legacy upgrade path strategy from: // https://github.com/facebook/jest/blob/v20.0.4/packages/jest-matchers/src/spyMatchers.js#L160 const isSpy = spy => spy.calls && typeof spy.calls.count === "function"; const spyOn = global.spyOn; const noop = function() {}; // Spying on console methods in production builds can mask errors. // This is why we added an explicit spyOnDev() helper. // It's too easy to accidentally use the more familiar spyOn() helper though, // So we disable it entirely. // Spying on both dev and prod will require using both spyOnDev() and spyOnProd(). global.spyOn = function() { throw new Error( "Do not use spyOn(). " + "It can accidentally hide unexpected errors in production builds. " + "Use spyOnDev(), spyOnProd(), or spyOnDevAndProd() instead." ); }; if (process.env.NODE_ENV === "production") { global.spyOnDev = noop; global.spyOnProd = spyOn; global.spyOnDevAndProd = spyOn; } else { global.spyOnDev = spyOn; global.spyOnProd = noop; global.spyOnDevAndProd = spyOn; } expect.extend(Object.assign({},require("./matchers/toWarnDev"))); // We have a Babel transform that inserts guards against infinite loops. // If a loop runs for too many iterations, we throw an error and set this // global variable. The global lets us detect an infinite loop even if // the actual error object ends up being caught and ignored. An infinite // loop must always fail the test! env.beforeEach(() => { global.infiniteLoopError = null; }); env.afterEach(() => { const error = global.infiniteLoopError; global.infiniteLoopError = null; if (error) { throw error; } }); ["error", "warn"].forEach(methodName => { const unexpectedConsoleCallStacks = []; const newMethod = function(message) { // Capture the call stack now so we can warn about it later. // The call stack has helpful information for the test author. // Don't throw yet though b'c it might be accidentally caught and suppressed. const stack = new Error().stack; unexpectedConsoleCallStacks.push([ stack.substr(stack.indexOf("\n") + 1), message, ]); }; console[methodName] = newMethod; env.beforeEach(() => { unexpectedConsoleCallStacks.length = 0; }); env.afterEach(() => { if (console[methodName] !== newMethod && !isSpy(console[methodName])) { throw new Error( `Test did not tear down console.${methodName} mock properly.` ); } if (unexpectedConsoleCallStacks.length > 0) { const messages = unexpectedConsoleCallStacks.map( ([stack, message]) => `${chalk.red(message)}\n` + `${stack .split("\n") .map(line => chalk.gray(line)) .join("\n")}` ); const message = `Expected test not to call ${chalk.bold( `console.${methodName}()` )}.\n\n` + "If the warning is expected, test for it explicitly by:\n" + `1. Using the ${chalk.bold(".toWarnDev()")} / ${chalk.bold( ".toLowPriorityWarnDev()" )} matchers, or...\n` + `2. Mock it out using ${chalk.bold("spyOnDev")}(console, '${ methodName }') or ${chalk.bold("spyOnProd")}(console, '${ methodName }'), and test that the warning occurs.`; throw new Error(`${message}\n\n${messages.join("\n\n")}`); } }); }); if (process.env.NODE_ENV === "production") { // In production, we strip error messages and turn them into codes. // This decodes them back so that the test assertions on them work. const decodeErrorMessage = function(message) { if (!message) { return message; } const re = /error-decoder.html\?invariant=(\d+)([^\s]*)/; const matches = message.match(re); if (!matches || matches.length !== 3) { return message; } const code = parseInt(matches[1], 10); const args = matches[2] .split("&") .filter(s => s.startsWith("args[]=")) .map(s => s.substr("args[]=".length)) .map(decodeURIComponent); const format = errorMap[code]; let argIndex = 0; return format.replace(/%s/g, () => args[argIndex++]); }; const OriginalError = global.Error; const ErrorProxy = new Proxy(OriginalError, { apply(target, thisArg, argumentsList) { const error = Reflect.apply(target, thisArg, argumentsList); error.message = decodeErrorMessage(error.message); return error; }, construct(target, argumentsList, newTarget) { const error = Reflect.construct(target, argumentsList, newTarget); error.message = decodeErrorMessage(error.message); return error; }, }); ErrorProxy.OriginalError = OriginalError; global.Error = ErrorProxy; } require("jasmine-check").install(); }