UNPKG

metaf-react

Version:

Resolvable component and injection root for adding DI/IoC to React App

159 lines 7.81 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MockRoot = void 0; var react_1 = __importDefault(require("react")); var ApplicationRoot_1 = require("./ApplicationRoot"); var Resolver_1 = require("./Resolver"); var renderWrappers = new WeakMap(); var resolveSymbol = 'MetaF Resolver, actually it should be a Symbol, but corresponding issue is still open (https://github.com/facebook/react/issues/7552)'; var defaultResolver = new Resolver_1.ReactResolver(); function addPropsToAll(children, resolve) { function recursiveClone(child) { var _a; if (!react_1.default.isValidElement(child)) return child; var resultingProps = typeof child.type === 'string' ? {} : (_a = {}, _a[resolveSymbol] = resolve, _a); var newChild = child; if (typeof child.type === 'function') { var renderFn = (child.type.prototype && child.type.prototype.render) ? child.type.prototype.render // we are in class component : child.type; // we are in single function component if (!renderWrappers.has(child.type)) { var renderWrapper_1 = { originalRender: renderFn, renders: new WeakMap(), }; var renderReplacement = function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } var props = (this === undefined) ? args[0] // we are in single function component, so props are in args : this.props; // we are in component, so props are in this var _a = props, _b = resolveSymbol, _c = _a[_b], particularResolver = _c === void 0 ? defaultResolver.resolveFor.bind(defaultResolver) : _c; var render = renderWrapper_1.renders.get(particularResolver) || renderWrapper_1.originalRender.bind(this); return render.apply(void 0, __spreadArray([this], __read(args), false)); }; if (child.type.prototype && child.type.prototype.render) child.type.prototype.render = renderReplacement; else newChild = __assign(__assign({}, child), { type: renderReplacement }); renderWrappers.set(newChild.type, renderWrapper_1); } // Next statement isn't undefined, because if there were no element for this key // previous block of code makes its initial setup, so when we reach this point its already there // tslint:disable-next-line:no-non-null-assertion var _b = renderWrappers.get(newChild.type), originalRender_1 = _b.originalRender, renders = _b.renders; if (!renders.get(resolve)) { renders.set(resolve, function (thisArg) { var args = []; for (var _i = 1; _i < arguments.length; _i++) { args[_i - 1] = arguments[_i]; } return addPropsToAll(originalRender_1.call.apply(originalRender_1, __spreadArray([thisArg], __read(args), false)), resolve); }); } } return react_1.default.cloneElement.apply(react_1.default, __spreadArray([newChild, resultingProps], __read((react_1.default.Children.map(child.props.children, recursiveClone) || [])), false)); } return react_1.default.Children.map(children, recursiveClone); } function resolveFor(classImpl, injections, instance, args) { if (injections === void 0) { injections = {}; } if (args === void 0) { args = []; } var _a = __read(args, 1), props = _a[0]; var _b = props, _c = resolveSymbol, _d = _b[_c], resolve = _d === void 0 ? defaultResolver.resolveFor.bind(defaultResolver) : _d; return resolve(classImpl, injections, instance, args); } var isResolverFnChangedToMock = false; /** * Exactly same as `ApplicationRoot` with only difference: * you are able to apply as many `MockRoot`s as your testing flow requires * @description MockRoot component * > **NOTE:** this component _MUST NOT_ be used as replacement for * `ApplicationRoot` in your production code, since it significantly affects * render flow in order to properly resolve dependencies for each subtree, * which may cause performance issues in some circumstances. * **BE AWARE THAT IT WAS DESIGNED FOR TESTING PURPOSES _ONLY_** */ var MockRoot = /** @class */ (function (_super) { __extends(MockRoot, _super); /** * Creates an instance of mock root. * @param props exactly same `props` as `ApplicationRoot` uses */ function MockRoot(props) { var _this = this; ApplicationRoot_1.config.shouldThrowForSeveralRoots = false; _this = _super.call(this, props) || this; if (!isResolverFnChangedToMock) { Resolver_1.resolver.resolveFor = resolveFor; isResolverFnChangedToMock = true; } _this.resolver = new Resolver_1.ReactResolver(props.dependencies); return _this; } MockRoot.prototype.render = function () { return addPropsToAll(this.wrapInHocs(), this.resolver.resolveFor.bind(this.resolver)); }; return MockRoot; }(ApplicationRoot_1.ApplicationRoot)); exports.MockRoot = MockRoot; //# sourceMappingURL=MockRoot.js.map