UNPKG

model-vue-presenter

Version:
118 lines (117 loc) 4.32 kB
import { isReadonly, getCurrentScope, onScopeDispose, computed } from "vue"; const ERROR = { PRESENTER_CONFIG: { INFO: "PresenterFactory: The configuration returned by the factory function is invalid.", get VIEW_MODEL_IS_NOT_COMPUTED() { return `${this.INFO} The 'viewModel' property must be a Vue computed property.`; }, get ON_CREATED_HOOK_NOT_A_FUNCTION() { return `${this.INFO} The 'onCreated' property must be a function.`; }, get ON_DESTROY_HOOK_NOT_A_FUNCTION() { return `${this.INFO} The 'onDestroy' property must be a function.`; } }, VIEW_MODEL_MOCKING: { INFO: "PresenterFactory: The mocked view model is invalid.", PROPERTIES_ARE_MISSING(properties) { return `${this.INFO} Properties ${properties} are missing in the mocked view model.`; }, HAS_NON_EXISTING_PROPERTIES(properties) { return `${this.INFO} Mocked view model properties ${properties} doesn't exist in the actual view model.`; } }, SPYING: { INFO: "PresenterFactory: Failed to spy on presenter.", get NO_PRESENTER_INSTANCE() { return `${this.INFO} Did you call your presenter hook before calling spy().`; } } }; function validatePresenterConfig(config) { if (!isReadonly(config.viewModel)) { throw new Error(ERROR.PRESENTER_CONFIG.VIEW_MODEL_IS_NOT_COMPUTED); } if (config.onCreated && typeof config.onCreated !== "function") { throw new Error(ERROR.PRESENTER_CONFIG.ON_CREATED_HOOK_NOT_A_FUNCTION); } if (config.onDestroy && typeof config.onDestroy !== "function") { throw new Error(ERROR.PRESENTER_CONFIG.ON_DESTROY_HOOK_NOT_A_FUNCTION); } } function validateViewModelOverride(viewModelOverride, actualViewModel) { const mockedViewModel = viewModelOverride(actualViewModel); const nonExistingProperties = Object.keys(mockedViewModel).filter((key) => !(key in actualViewModel)); const missingProperties = Object.keys(actualViewModel).filter((key) => !(key in mockedViewModel)); if (nonExistingProperties.length) { throw new Error(ERROR.VIEW_MODEL_MOCKING.HAS_NON_EXISTING_PROPERTIES(nonExistingProperties)); } if (missingProperties.length) { throw new Error(ERROR.VIEW_MODEL_MOCKING.PROPERTIES_ARE_MISSING(missingProperties)); } } function tryOnScopeDispose(fn) { if (getCurrentScope()) onScopeDispose(fn); } function presenterFactory(presenterFactoryFunction) { const cachedPresenterInstance = { value: void 0, reset() { this.value = void 0; } }; const viewModelOverride = { value: void 0, reset() { this.value = void 0; } }; function createPresenterProxy(presenterOptions, viewModelOverride2) { return new Proxy(presenterOptions, { get(target, property) { if (property === "viewModel") { return computed(() => viewModelOverride2(target.viewModel.value)); } return Reflect.get(target, property); } }); } function usePresenterHook(props, view) { var _a; const config = presenterFactoryFunction(props, view); validatePresenterConfig(config); if (viewModelOverride.value) validateViewModelOverride(viewModelOverride.value, config.viewModel.value); (_a = config.onCreated) == null ? void 0 : _a.call(config); tryOnScopeDispose(() => { var _a2; return (_a2 = config.onDestroy) == null ? void 0 : _a2.call(config); }); const presenterOptions = viewModelOverride.value ? createPresenterProxy(config, viewModelOverride.value) : config; cachedPresenterInstance.value = presenterOptions; viewModelOverride.reset(); return { presenter: presenterOptions, viewModel: presenterOptions.viewModel }; } usePresenterHook.spy = function() { const presenterOptions = cachedPresenterInstance.value; if (!presenterOptions) throw ERROR.SPYING.NO_PRESENTER_INSTANCE; cachedPresenterInstance.reset(); return { presenter: presenterOptions, viewModel: presenterOptions.viewModel }; }; usePresenterHook.resetSpy = function() { cachedPresenterInstance.reset(); }; usePresenterHook.mockViewModel = function(viewModelOverrideFunction) { viewModelOverride.value = viewModelOverrideFunction; }; return usePresenterHook; } export { presenterFactory }; //# sourceMappingURL=main.js.map