dreamstate
Version:
Store management library based on react context and observers
252 lines (237 loc) • 9.89 kB
JavaScript
;
var react = require('react');
var createProvider = require('./lib.js');
require('tslib');
require('shallow-equal');
/**
* Creates a mock scope provider with an initial clean state.
* This can be used to mock the entire scope context in a React tree.
*
* Must be used together with the `mockScope` method to ensure that the `value` property
* of `ScopeContext.Provider` is correctly set.
*
* @returns {Provider<IScopeContext>} A `ScopeContext.Provider` component for React rendering.
*/
function mockScopeProvider() {
return createProvider.ScopeContext.Provider;
}
/**
* Meta symbols for private internals in context managers for test-utils.
*/
var IS_MOCKED = Symbol("IS_MOCKED");
/**
* Creates a mock scope with a clean initial state.
* This can be used to mock the entire scope context for advanced testing.
*
* The `mockManagerInitialContext` function can be used to provision mocked contexts within this scope.
*
* @param {IMockScopeConfig} [mockConfig] - Configuration object for scope mocking.
* @param {IRegistry} [registry] - An optional custom registry to be used as the scope storage.
* @returns {IScopeContext} A mocked scope context.
*/
function mockScope(mockConfig, registry) {
if (mockConfig === void 0) {
mockConfig = {};
}
if (registry === void 0) {
registry = createProvider.createRegistry();
}
var _a = mockConfig.isLifecycleDisabled,
isLifecycleDisabled = _a === void 0 ? true : _a,
_b = mockConfig.applyInitialContexts,
applyInitialContexts = _b === void 0 ? [] : _b;
var appliedContexts = new Map(applyInitialContexts);
var scope = createProvider.createScope(registry);
/*
* Mark scope as mocked.
*/
Object.defineProperty(scope, IS_MOCKED, {
value: true
});
/*
* Mock service observer methods to exclude provision events from lifecycle.
*/
if (isLifecycleDisabled) {
var addServiceObserver_1 = scope.INTERNAL.addServiceObserver;
var removeServiceObserver_1 = scope.INTERNAL.removeServiceObserver;
scope.INTERNAL.addServiceObserver = function (ManagerClass, serviceObserver) {
return addServiceObserver_1(ManagerClass, serviceObserver, -1);
};
scope.INTERNAL.removeServiceObserver = function (ManagerClass, serviceObserver) {
return removeServiceObserver_1(ManagerClass, serviceObserver, -1);
};
}
/*
* Mock post-register contexts.
*/
if (appliedContexts.size) {
var registerService_1 = scope.INTERNAL.registerManager;
/*
* On register apply provided context from map parameter.
*/
scope.INTERNAL.registerManager = function (ManagerClass, initialState, _) {
return registerService_1(ManagerClass, initialState, appliedContexts.get(ManagerClass));
};
}
return scope;
}
/**
* Creates a mock context provider that constructs instances without firing provision events.
* This is useful for testing or mocking tree provision where required.
*
* @template T - The type of the provided context value, defaults to `TAnyObject`.
* @param {IContextManagerConstructor[]} sources - An array of context manager constructors that should be
* provided within the React tree when the returned component renders.
* @param {ICreateProviderProps} config - Configuration for the store provider.
* @param {boolean} config.isCombined - Determines whether to use a single large React node for observing
* changes or multiple smaller scoped nodes.
* @param {IScopeContext} scope - The scope where providers should be injected. Uses a mocked scope by default.
* @returns {FunctionComponent<IProviderProps<T>>} A mocked React provider component that provides the source
* classes within the mocked scope.
*/
function mockContextProvider(sources, config, scope) {
if (config === void 0) {
config = {};
}
if (scope === void 0) {
scope = mockScope();
}
var scopeProviderProps = {
value: scope
};
var ContextProvider = createProvider.createProvider(sources, config);
var ScopeProvider = mockScopeProvider();
/*
* Create provider component that can be used by react to automatically inject specific scope.
*/
function MockedProvider(props) {
return react.createElement(ScopeProvider, scopeProviderProps, react.createElement(ContextProvider, props));
}
/*
* Indicate that following provider is mocked.
*/
MockedProvider.displayName = "MockedProvider";
return MockedProvider;
}
/**
* Retrieves the current instance of a context manager from the given scope.
* Returns `null` if the manager is not found in the current scope.
*
* @template T - The type of the context manager constructor.
* @param {T} ManagerClass - The constructor reference of the context manager to retrieve.
* @param {IScopeContext} scope - The scope in which to search for the manager instance.
* @returns {InstanceType<T> | null} The instance of the specified manager class if found, otherwise `null`.
*/
function getCurrent(ManagerClass, scope) {
return scope.INTERNAL.REGISTRY.CONTEXT_INSTANCES_REGISTRY.get(ManagerClass) || null;
}
/**
* Mocks the initial context of a manager during service registration.
* This method ensures type safety by packaging the manager and its initial context in a structured way.
*
* @template D - The type of the context manager constructor.
* @param {D} ManagerClass - The manager class to which the initial context should be applied.
* @param {Partial<D["prototype"]["context"]>} context - A partial initial context to be used during provision.
* @returns {[D, Partial<D["prototype"]["context"]>]} A tuple containing the manager class and the provided
* initial context.
*/
function mockManagerInitialContext(ManagerClass, context) {
return [ManagerClass, context];
}
/**
* Creates a mocked internal registry for scope testing.
* This registry contains managers and listeners for testing purposes.
*
* @returns {IRegistry} The internal registry of managers and listeners.
*/
function mockRegistry() {
return createProvider.createRegistry();
}
/**
* Mocks a context manager for isolated testing.
*
* @template T - The type of the manager's state.
* @template S - The type of the initial state injected into the manager.
* @template M - The type of the context manager constructor.
* @param {M} ManagerClass - The constructor reference of the context manager to be created.
* @param {S | null} initialState - An optional initial state to inject into the manager's constructor.
* @param {IScopeContext} [scope] - An optional scope context where the manager
* should be mocked. If not provided, a new scope is created.
* @returns {InstanceType<M>} The instance of the mocked manager.
*/
function mockManager(ManagerClass, initialState, scope) {
if (scope === void 0) {
scope = createProvider.createScope();
}
scope.INTERNAL.registerManager(ManagerClass, initialState);
return scope.INTERNAL.REGISTRY.CONTEXT_INSTANCES_REGISTRY.get(ManagerClass);
}
/**
* Mocks multiple context managers and a scope for isolated testing.
*
* This is useful when multiple managers need to be paired together for specific test cases.
*
* @template T - The type of the manager's state.
* @template S - The type of the initial state injected into each manager.
* @template M - The type of a single context manager constructor.
* @param {M[]} managerClasses - An array of context manager constructor references to be created.
* @param {S | null} initialState - An optional initial state to inject into each manager's constructor.
* @param {IScopeContext} [scope] - The scope where managers should be mocked. A mocked scope is
* used by default.
* @returns {TManagerInstanceMap} A mapping of manager instances along with the mocked scope context.
*/
function mockManagers(managerClasses, initialState, scope) {
if (scope === void 0) {
scope = mockScope();
}
for (var it_1 = 0; it_1 < managerClasses.length; it_1++) {
scope.INTERNAL.registerManager(managerClasses[it_1], initialState);
}
return new Map(scope.INTERNAL.REGISTRY.CONTEXT_INSTANCES_REGISTRY);
}
/**
* Retrieves the React context consumer for the specified context manager.
*
* @template T - The type of the context manager constructor.
* @param {T} ManagerClass - The constructor reference of the context manager.
* @returns {Context<T["prototype"]["context"]>["Consumer"]} The React context consumer for the specified manager class.
*/
function getReactConsumer(ManagerClass) {
return ManagerClass.REACT_CONTEXT.Consumer;
}
/**
* Retrieves the React context provider for the specified context manager.
*
* @template T - The type of the context manager constructor.
* @param {T} ManagerClass - The constructor reference of the context manager.
* @returns {Context<T["prototype"]["context"]>["Provider"]} The React context provider for the specified manager class.
*/
function getReactProvider(ManagerClass) {
return ManagerClass.REACT_CONTEXT.Provider;
}
/**
* Waits for all queued events or a specified amount of time.
* This function is essentially a promisified `setTimeout`.
*
* @param {number} [ms] - The time in milliseconds to wait. Defaults to 0 if not specified.
* @returns {Promise<void>} A promise that resolves after the specified time has elapsed.
*/
function nextAsyncQueue(ms) {
if (ms === void 0) {
ms = 0;
}
return new Promise(function (resolve) {
return setTimeout(resolve, ms);
});
}
exports.getCurrent = getCurrent;
exports.getReactConsumer = getReactConsumer;
exports.getReactProvider = getReactProvider;
exports.mockContextProvider = mockContextProvider;
exports.mockManager = mockManager;
exports.mockManagerInitialContext = mockManagerInitialContext;
exports.mockManagers = mockManagers;
exports.mockRegistry = mockRegistry;
exports.mockScope = mockScope;
exports.mockScopeProvider = mockScopeProvider;
exports.nextAsyncQueue = nextAsyncQueue;