UNPKG

dreamstate

Version:

Store management library based on react context and observers

252 lines (237 loc) 9.89 kB
'use strict'; 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;