metaf-react
Version:
Resolvable component and injection root for adding DI/IoC to React App
159 lines • 7.81 kB
JavaScript
;
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