Best JavaScript code snippet using ng-mocks
hooks.js
Source:hooks.js
1/******/ (function() { // webpackBootstrap2/******/ "use strict";3/******/ // The require scope4/******/ var __webpack_require__ = {};5/******/ 6/************************************************************************/7/******/ /* webpack/runtime/define property getters */8/******/ !function() {9/******/ // define getter functions for harmony exports10/******/ __webpack_require__.d = function(exports, definition) {11/******/ for(var key in definition) {12/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {13/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });14/******/ }15/******/ }16/******/ };17/******/ }();18/******/ 19/******/ /* webpack/runtime/hasOwnProperty shorthand */20/******/ !function() {21/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }22/******/ }();23/******/ 24/******/ /* webpack/runtime/make namespace object */25/******/ !function() {26/******/ // define __esModule on exports27/******/ __webpack_require__.r = function(exports) {28/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {29/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });30/******/ }31/******/ Object.defineProperty(exports, '__esModule', { value: true });32/******/ };33/******/ }();34/******/ 35/************************************************************************/36var __webpack_exports__ = {};37// ESM COMPAT FLAG38__webpack_require__.r(__webpack_exports__);39// EXPORTS40__webpack_require__.d(__webpack_exports__, {41 "actions": function() { return /* binding */ actions; },42 "addAction": function() { return /* binding */ addAction; },43 "addFilter": function() { return /* binding */ addFilter; },44 "applyFilters": function() { return /* binding */ applyFilters; },45 "createHooks": function() { return /* reexport */ build_module_createHooks; },46 "currentAction": function() { return /* binding */ currentAction; },47 "currentFilter": function() { return /* binding */ currentFilter; },48 "defaultHooks": function() { return /* binding */ defaultHooks; },49 "didAction": function() { return /* binding */ didAction; },50 "didFilter": function() { return /* binding */ didFilter; },51 "doAction": function() { return /* binding */ doAction; },52 "doingAction": function() { return /* binding */ doingAction; },53 "doingFilter": function() { return /* binding */ doingFilter; },54 "filters": function() { return /* binding */ filters; },55 "hasAction": function() { return /* binding */ hasAction; },56 "hasFilter": function() { return /* binding */ hasFilter; },57 "removeAction": function() { return /* binding */ removeAction; },58 "removeAllActions": function() { return /* binding */ removeAllActions; },59 "removeAllFilters": function() { return /* binding */ removeAllFilters; },60 "removeFilter": function() { return /* binding */ removeFilter; }61});62;// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/validateNamespace.js63/**64 * Validate a namespace string.65 *66 * @param {string} namespace The namespace to validate - should take the form67 * `vendor/plugin/function`.68 *69 * @return {boolean} Whether the namespace is valid.70 */71function validateNamespace(namespace) {72 if ('string' !== typeof namespace || '' === namespace) {73 // eslint-disable-next-line no-console74 console.error('The namespace must be a non-empty string.');75 return false;76 }77 if (!/^[a-zA-Z][a-zA-Z0-9_.\-\/]*$/.test(namespace)) {78 // eslint-disable-next-line no-console79 console.error('The namespace can only contain numbers, letters, dashes, periods, underscores and slashes.');80 return false;81 }82 return true;83}84/* harmony default export */ var build_module_validateNamespace = (validateNamespace);85;// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/validateHookName.js86/**87 * Validate a hookName string.88 *89 * @param {string} hookName The hook name to validate. Should be a non empty string containing90 * only numbers, letters, dashes, periods and underscores. Also,91 * the hook name cannot begin with `__`.92 *93 * @return {boolean} Whether the hook name is valid.94 */95function validateHookName(hookName) {96 if ('string' !== typeof hookName || '' === hookName) {97 // eslint-disable-next-line no-console98 console.error('The hook name must be a non-empty string.');99 return false;100 }101 if (/^__/.test(hookName)) {102 // eslint-disable-next-line no-console103 console.error('The hook name cannot begin with `__`.');104 return false;105 }106 if (!/^[a-zA-Z][a-zA-Z0-9_.-]*$/.test(hookName)) {107 // eslint-disable-next-line no-console108 console.error('The hook name can only contain numbers, letters, dashes, periods and underscores.');109 return false;110 }111 return true;112}113/* harmony default export */ var build_module_validateHookName = (validateHookName);114;// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/createAddHook.js115/**116 * Internal dependencies117 */118/**119 * @callback AddHook120 *121 * Adds the hook to the appropriate hooks container.122 *123 * @param {string} hookName Name of hook to add124 * @param {string} namespace The unique namespace identifying the callback in the form `vendor/plugin/function`.125 * @param {import('.').Callback} callback Function to call when the hook is run126 * @param {number} [priority=10] Priority of this hook127 */128/**129 * Returns a function which, when invoked, will add a hook.130 *131 * @param {import('.').Hooks} hooks Hooks instance.132 * @param {import('.').StoreKey} storeKey133 *134 * @return {AddHook} Function that adds a new hook.135 */136function createAddHook(hooks, storeKey) {137 return function addHook(hookName, namespace, callback) {138 let priority = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 10;139 const hooksStore = hooks[storeKey];140 if (!build_module_validateHookName(hookName)) {141 return;142 }143 if (!build_module_validateNamespace(namespace)) {144 return;145 }146 if ('function' !== typeof callback) {147 // eslint-disable-next-line no-console148 console.error('The hook callback must be a function.');149 return;150 } // Validate numeric priority151 if ('number' !== typeof priority) {152 // eslint-disable-next-line no-console153 console.error('If specified, the hook priority must be a number.');154 return;155 }156 const handler = {157 callback,158 priority,159 namespace160 };161 if (hooksStore[hookName]) {162 // Find the correct insert index of the new hook.163 const handlers = hooksStore[hookName].handlers;164 /** @type {number} */165 let i;166 for (i = handlers.length; i > 0; i--) {167 if (priority >= handlers[i - 1].priority) {168 break;169 }170 }171 if (i === handlers.length) {172 // If append, operate via direct assignment.173 handlers[i] = handler;174 } else {175 // Otherwise, insert before index via splice.176 handlers.splice(i, 0, handler);177 } // We may also be currently executing this hook. If the callback178 // we're adding would come after the current callback, there's no179 // problem; otherwise we need to increase the execution index of180 // any other runs by 1 to account for the added element.181 hooksStore.__current.forEach(hookInfo => {182 if (hookInfo.name === hookName && hookInfo.currentIndex >= i) {183 hookInfo.currentIndex++;184 }185 });186 } else {187 // This is the first hook of its type.188 hooksStore[hookName] = {189 handlers: [handler],190 runs: 0191 };192 }193 if (hookName !== 'hookAdded') {194 hooks.doAction('hookAdded', hookName, namespace, callback, priority);195 }196 };197}198/* harmony default export */ var build_module_createAddHook = (createAddHook);199;// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/createRemoveHook.js200/**201 * Internal dependencies202 */203/**204 * @callback RemoveHook205 * Removes the specified callback (or all callbacks) from the hook with a given hookName206 * and namespace.207 *208 * @param {string} hookName The name of the hook to modify.209 * @param {string} namespace The unique namespace identifying the callback in the210 * form `vendor/plugin/function`.211 *212 * @return {number | undefined} The number of callbacks removed.213 */214/**215 * Returns a function which, when invoked, will remove a specified hook or all216 * hooks by the given name.217 *218 * @param {import('.').Hooks} hooks Hooks instance.219 * @param {import('.').StoreKey} storeKey220 * @param {boolean} [removeAll=false] Whether to remove all callbacks for a hookName,221 * without regard to namespace. Used to create222 * `removeAll*` functions.223 *224 * @return {RemoveHook} Function that removes hooks.225 */226function createRemoveHook(hooks, storeKey) {227 let removeAll = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;228 return function removeHook(hookName, namespace) {229 const hooksStore = hooks[storeKey];230 if (!build_module_validateHookName(hookName)) {231 return;232 }233 if (!removeAll && !build_module_validateNamespace(namespace)) {234 return;235 } // Bail if no hooks exist by this name.236 if (!hooksStore[hookName]) {237 return 0;238 }239 let handlersRemoved = 0;240 if (removeAll) {241 handlersRemoved = hooksStore[hookName].handlers.length;242 hooksStore[hookName] = {243 runs: hooksStore[hookName].runs,244 handlers: []245 };246 } else {247 // Try to find the specified callback to remove.248 const handlers = hooksStore[hookName].handlers;249 for (let i = handlers.length - 1; i >= 0; i--) {250 if (handlers[i].namespace === namespace) {251 handlers.splice(i, 1);252 handlersRemoved++; // This callback may also be part of a hook that is253 // currently executing. If the callback we're removing254 // comes after the current callback, there's no problem;255 // otherwise we need to decrease the execution index of any256 // other runs by 1 to account for the removed element.257 hooksStore.__current.forEach(hookInfo => {258 if (hookInfo.name === hookName && hookInfo.currentIndex >= i) {259 hookInfo.currentIndex--;260 }261 });262 }263 }264 }265 if (hookName !== 'hookRemoved') {266 hooks.doAction('hookRemoved', hookName, namespace);267 }268 return handlersRemoved;269 };270}271/* harmony default export */ var build_module_createRemoveHook = (createRemoveHook);272;// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/createHasHook.js273/**274 * @callback HasHook275 *276 * Returns whether any handlers are attached for the given hookName and optional namespace.277 *278 * @param {string} hookName The name of the hook to check for.279 * @param {string} [namespace] Optional. The unique namespace identifying the callback280 * in the form `vendor/plugin/function`.281 *282 * @return {boolean} Whether there are handlers that are attached to the given hook.283 */284/**285 * Returns a function which, when invoked, will return whether any handlers are286 * attached to a particular hook.287 *288 * @param {import('.').Hooks} hooks Hooks instance.289 * @param {import('.').StoreKey} storeKey290 *291 * @return {HasHook} Function that returns whether any handlers are292 * attached to a particular hook and optional namespace.293 */294function createHasHook(hooks, storeKey) {295 return function hasHook(hookName, namespace) {296 const hooksStore = hooks[storeKey]; // Use the namespace if provided.297 if ('undefined' !== typeof namespace) {298 return hookName in hooksStore && hooksStore[hookName].handlers.some(hook => hook.namespace === namespace);299 }300 return hookName in hooksStore;301 };302}303/* harmony default export */ var build_module_createHasHook = (createHasHook);304;// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/createRunHook.js305/**306 * Returns a function which, when invoked, will execute all callbacks307 * registered to a hook of the specified type, optionally returning the final308 * value of the call chain.309 *310 * @param {import('.').Hooks} hooks Hooks instance.311 * @param {import('.').StoreKey} storeKey312 * @param {boolean} [returnFirstArg=false] Whether each hook callback is expected to313 * return its first argument.314 *315 * @return {(hookName:string, ...args: unknown[]) => unknown} Function that runs hook callbacks.316 */317function createRunHook(hooks, storeKey) {318 let returnFirstArg = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;319 return function runHooks(hookName) {320 const hooksStore = hooks[storeKey];321 if (!hooksStore[hookName]) {322 hooksStore[hookName] = {323 handlers: [],324 runs: 0325 };326 }327 hooksStore[hookName].runs++;328 const handlers = hooksStore[hookName].handlers; // The following code is stripped from production builds.329 if (false) {}330 for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {331 args[_key - 1] = arguments[_key];332 }333 if (!handlers || !handlers.length) {334 return returnFirstArg ? args[0] : undefined;335 }336 const hookInfo = {337 name: hookName,338 currentIndex: 0339 };340 hooksStore.__current.push(hookInfo);341 while (hookInfo.currentIndex < handlers.length) {342 const handler = handlers[hookInfo.currentIndex];343 const result = handler.callback.apply(null, args);344 if (returnFirstArg) {345 args[0] = result;346 }347 hookInfo.currentIndex++;348 }349 hooksStore.__current.pop();350 if (returnFirstArg) {351 return args[0];352 }353 };354}355/* harmony default export */ var build_module_createRunHook = (createRunHook);356;// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/createCurrentHook.js357/**358 * Returns a function which, when invoked, will return the name of the359 * currently running hook, or `null` if no hook of the given type is currently360 * running.361 *362 * @param {import('.').Hooks} hooks Hooks instance.363 * @param {import('.').StoreKey} storeKey364 *365 * @return {() => string | null} Function that returns the current hook name or null.366 */367function createCurrentHook(hooks, storeKey) {368 return function currentHook() {369 var _hooksStore$__current, _hooksStore$__current2;370 const hooksStore = hooks[storeKey];371 return (_hooksStore$__current = (_hooksStore$__current2 = hooksStore.__current[hooksStore.__current.length - 1]) === null || _hooksStore$__current2 === void 0 ? void 0 : _hooksStore$__current2.name) !== null && _hooksStore$__current !== void 0 ? _hooksStore$__current : null;372 };373}374/* harmony default export */ var build_module_createCurrentHook = (createCurrentHook);375;// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/createDoingHook.js376/**377 * @callback DoingHook378 * Returns whether a hook is currently being executed.379 *380 * @param {string} [hookName] The name of the hook to check for. If381 * omitted, will check for any hook being executed.382 *383 * @return {boolean} Whether the hook is being executed.384 */385/**386 * Returns a function which, when invoked, will return whether a hook is387 * currently being executed.388 *389 * @param {import('.').Hooks} hooks Hooks instance.390 * @param {import('.').StoreKey} storeKey391 *392 * @return {DoingHook} Function that returns whether a hook is currently393 * being executed.394 */395function createDoingHook(hooks, storeKey) {396 return function doingHook(hookName) {397 const hooksStore = hooks[storeKey]; // If the hookName was not passed, check for any current hook.398 if ('undefined' === typeof hookName) {399 return 'undefined' !== typeof hooksStore.__current[0];400 } // Return the __current hook.401 return hooksStore.__current[0] ? hookName === hooksStore.__current[0].name : false;402 };403}404/* harmony default export */ var build_module_createDoingHook = (createDoingHook);405;// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/createDidHook.js406/**407 * Internal dependencies408 */409/**410 * @callback DidHook411 *412 * Returns the number of times an action has been fired.413 *414 * @param {string} hookName The hook name to check.415 *416 * @return {number | undefined} The number of times the hook has run.417 */418/**419 * Returns a function which, when invoked, will return the number of times a420 * hook has been called.421 *422 * @param {import('.').Hooks} hooks Hooks instance.423 * @param {import('.').StoreKey} storeKey424 *425 * @return {DidHook} Function that returns a hook's call count.426 */427function createDidHook(hooks, storeKey) {428 return function didHook(hookName) {429 const hooksStore = hooks[storeKey];430 if (!build_module_validateHookName(hookName)) {431 return;432 }433 return hooksStore[hookName] && hooksStore[hookName].runs ? hooksStore[hookName].runs : 0;434 };435}436/* harmony default export */ var build_module_createDidHook = (createDidHook);437;// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/createHooks.js438/**439 * Internal dependencies440 */441/**442 * Internal class for constructing hooks. Use `createHooks()` function443 *444 * Note, it is necessary to expose this class to make its type public.445 *446 * @private447 */448class _Hooks {449 constructor() {450 /** @type {import('.').Store} actions */451 this.actions = Object.create(null);452 this.actions.__current = [];453 /** @type {import('.').Store} filters */454 this.filters = Object.create(null);455 this.filters.__current = [];456 this.addAction = build_module_createAddHook(this, 'actions');457 this.addFilter = build_module_createAddHook(this, 'filters');458 this.removeAction = build_module_createRemoveHook(this, 'actions');459 this.removeFilter = build_module_createRemoveHook(this, 'filters');460 this.hasAction = build_module_createHasHook(this, 'actions');461 this.hasFilter = build_module_createHasHook(this, 'filters');462 this.removeAllActions = build_module_createRemoveHook(this, 'actions', true);463 this.removeAllFilters = build_module_createRemoveHook(this, 'filters', true);464 this.doAction = build_module_createRunHook(this, 'actions');465 this.applyFilters = build_module_createRunHook(this, 'filters', true);466 this.currentAction = build_module_createCurrentHook(this, 'actions');467 this.currentFilter = build_module_createCurrentHook(this, 'filters');468 this.doingAction = build_module_createDoingHook(this, 'actions');469 this.doingFilter = build_module_createDoingHook(this, 'filters');470 this.didAction = build_module_createDidHook(this, 'actions');471 this.didFilter = build_module_createDidHook(this, 'filters');472 }473}474/** @typedef {_Hooks} Hooks */475/**476 * Returns an instance of the hooks object.477 *478 * @return {Hooks} A Hooks instance.479 */480function createHooks() {481 return new _Hooks();482}483/* harmony default export */ var build_module_createHooks = (createHooks);484;// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/index.js485/**486 * Internal dependencies487 */488/** @typedef {(...args: any[])=>any} Callback */489/**490 * @typedef Handler491 * @property {Callback} callback The callback492 * @property {string} namespace The namespace493 * @property {number} priority The namespace494 */495/**496 * @typedef Hook497 * @property {Handler[]} handlers Array of handlers498 * @property {number} runs Run counter499 */500/**501 * @typedef Current502 * @property {string} name Hook name503 * @property {number} currentIndex The index504 */505/**506 * @typedef {Record<string, Hook> & {__current: Current[]}} Store507 */508/**509 * @typedef {'actions' | 'filters'} StoreKey510 */511/**512 * @typedef {import('./createHooks').Hooks} Hooks513 */514const defaultHooks = build_module_createHooks();515const {516 addAction,517 addFilter,518 removeAction,519 removeFilter,520 hasAction,521 hasFilter,522 removeAllActions,523 removeAllFilters,524 doAction,525 applyFilters,526 currentAction,527 currentFilter,528 doingAction,529 doingFilter,530 didAction,531 didFilter,532 actions,533 filters534} = defaultHooks;535(window.wp = window.wp || {}).hooks = __webpack_exports__;536/******/ })()...
PluginHooks.spec.js
Source:PluginHooks.spec.js
1describe('PluginHooks', function () {2 var id = 'testContainer';3 beforeEach(function () {4 this.$container = $('<div id="' + id + '"></div>').appendTo('body');5 });6 afterEach(function () {7 if (this.$container) {8 destroy();9 this.$container.remove();10 }11 });12 describe('unit tests', function() {13 it('should create global empty bucket on construct', function () {14 var hooks = new Handsontable.utils.Hooks();15 expect(hooks.globalBucket).toBeDefined();16 expect(hooks.globalBucket.afterInit).toEqual([]);17 expect(hooks.globalBucket.beforeInit).toEqual([]);18 expect(hooks.globalBucket.init).toEqual([]);19 });20 it('should create empty object (bucket) on createEmptyBucket call', function () {21 var hooks = new Handsontable.utils.Hooks();22 var bucket = hooks.createEmptyBucket();23 expect(bucket.afterInit).toEqual([]);24 expect(bucket.beforeInit).toEqual([]);25 expect(bucket.init).toEqual([]);26 expect(bucket).not.toBe(hooks.createEmptyBucket());27 });28 it('should create and get local bucket when context is passed', function () {29 var hooks = new Handsontable.utils.Hooks();30 var context = {};31 var bucket = hooks.getBucket(context);32 expect(context.pluginHookBucket).toBeDefined();33 expect(context.pluginHookBucket).toBe(bucket);34 });35 it('should get global bucket when context is empty', function () {36 var hooks = new Handsontable.utils.Hooks();37 var bucket = hooks.getBucket();38 expect(bucket).toBe(hooks.globalBucket);39 });40 it('should add hooks as array', function () {41 var hooks = new Handsontable.utils.Hooks();42 var fn1 = function () {};43 var fn2 = function () {};44 var fn3 = function () {};45 var context = {};46 var bucket = {};47 spyOn(hooks, 'getBucket').and.returnValue(bucket);48 spyOn(hooks, 'register');49 hooks.add('test', [fn1, fn2, fn3, fn3, fn3], context);50 expect(hooks.getBucket.calls.count()).toBe(5);51 expect(hooks.getBucket.calls.mostRecent()).toEqual({object: hooks, args: [{}], returnValue: bucket});52 expect(hooks.register.calls.count()).toBe(1);53 expect(hooks.register.calls.mostRecent()).toEqual({object: hooks, args: ['test'], returnValue: void 0});54 expect(bucket.test.length).toBe(3);55 expect(bucket.test[0]).toBe(fn1);56 expect(bucket.test[1]).toBe(fn2);57 expect(bucket.test[2]).toBe(fn3);58 });59 it('should add hook as function', function () {60 var hooks = new Handsontable.utils.Hooks();61 var fn1 = function () {};62 var fn2 = function () {};63 var context = {};64 var bucket = {test: []};65 spyOn(hooks, 'getBucket').and.returnValue(bucket);66 spyOn(hooks, 'register');67 hooks.add('test', fn1, context);68 hooks.add('test', fn1);69 hooks.add('test', fn2, context);70 expect(hooks.getBucket.calls.count()).toBe(3);71 expect(hooks.getBucket.calls.argsFor(0)[0]).toBe(context);72 expect(hooks.getBucket.calls.argsFor(1)[0]).toBe(null);73 expect(hooks.getBucket.calls.argsFor(2)[0]).toBe(context);74 expect(hooks.register).not.toHaveBeenCalled();75 expect(bucket.test.length).toBe(2);76 expect(bucket.test[0]).toBe(fn1);77 expect(bucket.test[1]).toBe(fn2);78 });79 it('should add hook once as array', function () {80 var hooks = new Handsontable.utils.Hooks();81 var fn1 = function () {};82 var fn2 = function () {};83 var fn3 = function () {};84 var context = {};85 var bucket = {};86 spyOn(hooks, 'add');87 hooks.once('test', [fn1, fn2, fn3, fn3, fn3], context);88 expect(fn1.runOnce).toBe(true);89 expect(fn2.runOnce).toBe(true);90 expect(fn3.runOnce).toBe(true);91 expect(hooks.add.calls.count()).toBe(5);92 expect(hooks.add.calls.mostRecent()).toEqual({object: hooks, args: ['test', fn3, context], returnValue: void 0});93 });94 it('should add hook once as function', function () {95 var hooks = new Handsontable.utils.Hooks();96 var fn1 = function () {};97 var fn2 = function () {};98 var context = {};99 var bucket = {};100 spyOn(hooks, 'add');101 hooks.once('test', fn1, context);102 hooks.once('test', fn2);103 expect(fn1.runOnce).toBe(true);104 expect(fn2.runOnce).toBe(true);105 expect(hooks.add.calls.count()).toBe(2);106 expect(hooks.add.calls.argsFor(0)[0]).toBe('test')107 expect(hooks.add.calls.argsFor(0)[1]).toBe(fn1);108 expect(hooks.add.calls.argsFor(0)[2]).toBe(context);109 expect(hooks.add.calls.argsFor(1)[0]).toBe('test')110 expect(hooks.add.calls.argsFor(1)[1]).toBe(fn2);111 expect(hooks.add.calls.argsFor(1)[2]).toBe(null);112 });113 it('should remove hook', function () {114 var hooks = new Handsontable.utils.Hooks();115 var fn1 = function () {};116 var fn2 = function () {};117 var fn3 = function () {};118 var context = {};119 var bucket = {test: [fn1, fn2]};120 var result;121 spyOn(hooks, 'getBucket').and.returnValue(bucket);122 result = hooks.remove('test2', fn1);123 expect(result).toBe(false);124 expect(bucket.test.length).toBe(2);125 result = hooks.remove('test', fn3);126 expect(result).toBe(false);127 expect(bucket.test.length).toBe(2);128 result = hooks.remove('test', fn1);129 expect(result).toBe(true);130 expect(bucket.test[0].skip).toBe(true);131 expect(bucket.test.length).toBe(2);132 });133 it('should run hook', function () {134 var hooks = new Handsontable.utils.Hooks();135 var fn1 = jasmine.createSpy('fn1').and.returnValue('Foo');136 var fn2 = jasmine.createSpy('fn2').and.returnValue('Bar');137 var fn3 = jasmine.createSpy('fn3');138 var context = {};139 var bucket = {test: [fn1, fn2]};140 var result;141 hooks.globalBucket.test = [fn3];142 spyOn(hooks, 'getBucket').and.returnValue(bucket);143 spyOn(hooks, 'remove');144 result = hooks.run(context, 'test');145 expect(result).toBe('Bar');146 expect(hooks.getBucket).toHaveBeenCalledWith(context);147 expect(hooks.remove).not.toHaveBeenCalled();148 expect(fn1).toHaveBeenCalled();149 expect(fn2).toHaveBeenCalled();150 expect(fn3).toHaveBeenCalled();151 fn1.calls.reset();152 fn1.runOnce = true;153 fn2.calls.reset();154 fn3.calls.reset();155 result = hooks.run(context, 'test', 1, 2, 'AB');156 expect(result).toBe('Bar');157 expect(hooks.remove).toHaveBeenCalledWith('test', fn1, context);158 expect(fn1).toHaveBeenCalledWith(1, 2, 'AB', void 0, void 0, void 0);159 expect(fn2).toHaveBeenCalledWith('Foo', 2, 'AB', void 0, void 0, void 0);160 expect(fn3).toHaveBeenCalledWith(1, 2, 'AB', void 0, void 0, void 0);161 });162 it('should run hooks added as once', function () {163 var hooks = new Handsontable.utils.Hooks();164 var fn1 = jasmine.createSpy('fn1').and.returnValue('Foo');165 var fn2 = jasmine.createSpy('fn2').and.returnValue('Bar');166 var fn3 = jasmine.createSpy('fn3');167 var context = {pluginHookBucket: {test: [fn1, fn2]}};168 var result;169 fn1.runOnce = true;170 fn2.runOnce = true;171 fn3.runOnce = true;172 hooks.globalBucket = {test: [fn3]}173 hooks.run(context, 'test');174 hooks.run(context, 'test');175 hooks.run(context, 'test');176 expect(fn1.calls.count()).toBe(1);177 expect(fn2.calls.count()).toBe(1);178 expect(fn3.calls.count()).toBe(1);179 });180 it('should destroy hooks', function () {181 var hooks = new Handsontable.utils.Hooks();182 var fn1 = jasmine.createSpy('fn1').and.returnValue('Foo');183 var fn2 = jasmine.createSpy('fn2').and.returnValue('Bar');184 var fn3 = jasmine.createSpy('fn3');185 var context = {};186 var bucket = {test: [fn1, fn2, fn3], test2: [fn3]};187 spyOn(hooks, 'getBucket').and.returnValue(bucket);188 hooks.destroy(context);189 expect(hooks.getBucket).toHaveBeenCalledWith(context);190 expect(bucket.test.length).toBe(0);191 expect(bucket.test2.length).toBe(0);192 });193 it('should register hook', function () {194 var hooks = new Handsontable.utils.Hooks();195 spyOn(hooks, 'isRegistered').and.returnValue(false);196 hooks.register('test');197 expect(hooks.isRegistered).toHaveBeenCalledWith('test');198 expect(hooks.getRegistered().indexOf('test')).toBeGreaterThan(-1);199 hooks.isRegistered.and.returnValue(true);200 hooks.register('test2');201 expect(hooks.isRegistered).toHaveBeenCalledWith('test2');202 expect(hooks.getRegistered().indexOf('test2')).toBe(-1);203 });204 it('should deregister hook', function () {205 var hooks = new Handsontable.utils.Hooks();206 spyOn(hooks, 'isRegistered').and.returnValue(false);207 hooks.register('test');208 hooks.deregister('test');209 expect(hooks.isRegistered).toHaveBeenCalledWith('test');210 expect(hooks.getRegistered().indexOf('test')).toBeGreaterThan(-1);211 hooks.isRegistered.and.returnValue(true);212 hooks.deregister('test2');213 expect(hooks.isRegistered).toHaveBeenCalledWith('test2');214 expect(hooks.getRegistered().indexOf('test2')).toBe(-1);215 });216 it('should returns `true` if hooks is registered', function () {217 var hooks = new Handsontable.utils.Hooks();218 hooks.register('test');219 expect(hooks.isRegistered('test')).toBe(true);220 expect(hooks.isRegistered('test2')).toBe(false);221 });222 it('should returns array of registered hooks', function () {223 var hooks = new Handsontable.utils.Hooks();224 expect(hooks.getRegistered().length).toBeGreaterThan(0);225 });226 it('should returns `true` if at least one listener was added to the hook', function () {227 var hooks = new Handsontable.utils.Hooks();228 var context = {};229 expect(hooks.has('beforeInit', context)).toBe(false);230 hooks.add('beforeInit', function() {}, context);231 expect(hooks.has('beforeInit', context)).toBe(true);232 });233 });234 it('should add a many local hooks at init (as array)', function () {235 var handler1 = jasmine.createSpy('handler1');236 var handler2 = jasmine.createSpy('handler2');237 var handler3 = jasmine.createSpy('handler3');238 handsontable({239 afterInit: [handler1, handler2, handler3]240 });241 expect(handler1).toHaveBeenCalled();242 expect(handler2).toHaveBeenCalled();243 expect(handler3).toHaveBeenCalled();244 });245 it('should remove a global hook', function () {246 var247 test = 0,248 hook = function () {249 test = 5;250 };251 Handsontable.hooks.add('afterInit', hook);252 Handsontable.hooks.remove('afterInit', hook);253 handsontable();254 expect(test).toEqual(0);255 });256 it('should remove a local hook', function () {257 var258 test = 0,259 hook = function () {260 test = 5;261 };262 handsontable();263 getInstance().addHook('afterInit', hook);264 getInstance().removeHook('afterInit', hook);265 expect(test).toEqual(0);266 });267 it('should run global hook', function () {268 var test = 0;269 Handsontable.hooks.add('afterInit', function () {270 test = 5;271 });272 handsontable();273 expect(test).toEqual(5);274 });275 it('should run local hook', function () {276 var test = 0;277 handsontable();278 getInstance().addHook('myHook', function () {279 test += 5;280 });281 getInstance().runHooks('myHook');282 getInstance().runHooks('myHook');283 expect(test).toEqual(10);284 });285 it('should run local hook once', function () {286 var test = 0;287 handsontable();288 getInstance().addHookOnce('myHook', function () {289 test += 5;290 });291 getInstance().runHooks('myHook');292 getInstance().runHooks('myHook');293 expect(test).toEqual(5);294 });295 it('should run all hooks', function () {296 var test = 0;297 Handsontable.hooks.add('afterInit', function () {298 test += 5;299 });300 handsontable({301 afterInit: function () {302 test += 5;303 }304 });305 expect(test).toEqual(10);306 });307 it('list of all avaliable plugin hooks should be exposed as a public method', function () {308 var hooks = Handsontable.hooks.getRegistered(); //this is used in demo/callbacks.html309 expect(hooks.indexOf('beforeInit')).toBeGreaterThan(-1);310 });311 it('should add a local hook with addHooks method', function(){312 var hot1 = handsontable();313 var test = 0;314 hot1.addHook('myHook', function(){315 test += 5;316 });317 hot1.runHooks('myHook');318 expect(test).toEqual(5);319 });320 it('should remove a local hook with removeHook method', function(){321 var hot1 = handsontable();322 var test = 0;323 var handler = function(){324 test += 5;325 };326 hot1.addHook('myHook', handler);327 hot1.runHooks('myHook');328 hot1.runHooks('myHook');329 expect(test).toEqual(10);330 hot1.removeHook('myHook', handler);331 hot1.runHooks('myHook');332 expect(test).toEqual(10);333 });334 it('should add a local hook with addHookOnce method and run it just once', function(){335 var hot1 = handsontable();336 var test = 0;337 var handler = function(){338 test += 5;339 };340 hot1.addHookOnce('myHook', handler);341 hot1.runHooks('myHook');342 hot1.runHooks('myHook');343 expect(test).toEqual(5);344 });345 it('should run hook with runHooks and return value', function(){346 var hot = handsontable();347 var handler = function(){348 return 5;349 };350 hot.addHook('myHook', handler);351 expect(hot.runHooks('myHook')).toEqual(5);352 });353 it('should run two "once" hooks in desired order', function(){354 var hot = handsontable();355 var arr = [];356 hot.addHookOnce('myHook', function(){357 arr.push(1);358 });359 hot.addHookOnce('myHook', function(){360 arr.push(2);361 });362 hot.runHooks('myHook');363 expect(arr).toEqual([1,2]);364 });365 it('should execute two "once" hooks in desired order', function(){366 var hot = handsontable();367 var str = 'a';368 hot.addHookOnce('myHook', function(str){369 return str + 'b';370 });371 hot.addHookOnce('myHook', function(str){372 return str + 'c';373 });374 expect(hot.runHooks('myHook', str)).toEqual('abc');375 });376 it('adding same hook twice should register it only once (without an error)', function () {377 var i = 0;378 var fn = function(){379 i++;380 };381 var hot = handsontable({382 afterOnCellMouseOver: fn383 });384 hot.getInstance().updateSettings({afterOnCellMouseOver: fn});385 hot.runHooks('afterOnCellMouseOver');386 expect(i).toEqual(1);387 });388 describe("controlling handler queue execution", function () {389 it("should execute all handlers if none of them hasn't skipped", function () {390 var handler1 = jasmine.createSpy('handler1');391 var handler2 = jasmine.createSpy('handler2');392 var handler3 = jasmine.createSpy('handler3');393 var hot = handsontable();394 hot.addHook('fakeEvent', handler1);395 hot.addHook('fakeEvent', handler2);396 hot.addHook('fakeEvent', handler3);397 expect(handler1).not.toHaveBeenCalled();398 expect(handler2).not.toHaveBeenCalled();399 expect(handler3).not.toHaveBeenCalled();400 hot.runHooks('fakeEvent');401 expect(handler1).toHaveBeenCalled();402 expect(handler2).toHaveBeenCalled();403 expect(handler3).toHaveBeenCalled();404 });405 });...
examples.test.js
Source:examples.test.js
1var assert = require('assert');2var Kareem = require('../');3/* Much like [hooks](https://npmjs.org/package/hooks), kareem lets you define4 * pre and post hooks: pre hooks are called before a given function executes.5 * Unlike hooks, kareem stores hooks and other internal state in a separate6 * object, rather than relying on inheritance. Furthermore, kareem exposes7 * an `execPre()` function that allows you to execute your pre hooks when8 * appropriate, giving you more fine-grained control over your function hooks.9 */10describe('pre hooks', function() {11 var hooks;12 beforeEach(function() {13 hooks = new Kareem();14 });15 it('runs without any hooks specified', function(done) {16 hooks.execPre('cook', null, function() {17 // ...18 // acquit:ignore:start19 done();20 // acquit:ignore:end21 });22 });23 /* pre hook functions take one parameter, a "done" function that you execute24 * when your pre hook is finished.25 */26 it('runs basic serial pre hooks', function(done) {27 var count = 0;28 hooks.pre('cook', function(done) {29 ++count;30 done();31 });32 hooks.execPre('cook', null, function() {33 assert.equal(1, count);34 // acquit:ignore:start35 done();36 // acquit:ignore:end37 });38 });39 it('can run multipe pre hooks', function(done) {40 var count1 = 0;41 var count2 = 0;42 hooks.pre('cook', function(done) {43 ++count1;44 done();45 });46 hooks.pre('cook', function(done) {47 ++count2;48 done();49 });50 hooks.execPre('cook', null, function() {51 assert.equal(1, count1);52 assert.equal(1, count2);53 // acquit:ignore:start54 done();55 // acquit:ignore:end56 });57 });58 /* If your pre hook function takes no parameters, its assumed to be59 * fully synchronous.60 */61 it('can run fully synchronous pre hooks', function(done) {62 var count1 = 0;63 var count2 = 0;64 hooks.pre('cook', function() {65 ++count1;66 });67 hooks.pre('cook', function() {68 ++count2;69 });70 hooks.execPre('cook', null, function(error) {71 assert.equal(null, error);72 assert.equal(1, count1);73 assert.equal(1, count2);74 // acquit:ignore:start75 done();76 // acquit:ignore:end77 });78 });79 /* Pre save hook functions are bound to the second parameter to `execPre()`80 */81 it('properly attaches context to pre hooks', function(done) {82 hooks.pre('cook', function(done) {83 this.bacon = 3;84 done();85 });86 hooks.pre('cook', function(done) {87 this.eggs = 4;88 done();89 });90 var obj = { bacon: 0, eggs: 0 };91 // In the pre hooks, `this` will refer to `obj`92 hooks.execPre('cook', obj, function(error) {93 assert.equal(null, error);94 assert.equal(3, obj.bacon);95 assert.equal(4, obj.eggs);96 // acquit:ignore:start97 done();98 // acquit:ignore:end99 });100 });101 /* Like the hooks module, you can declare "async" pre hooks - these take two102 * parameters, the functions `next()` and `done()`. `next()` passes control to103 * the next pre hook, but the underlying function won't be called until all104 * async pre hooks have called `done()`.105 */106 it('can execute parallel (async) pre hooks', function(done) {107 hooks.pre('cook', true, function(next, done) {108 this.bacon = 3;109 next();110 setTimeout(function() {111 done();112 }, 5);113 });114 hooks.pre('cook', true, function(next, done) {115 next();116 var _this = this;117 setTimeout(function() {118 _this.eggs = 4;119 done();120 }, 10);121 });122 hooks.pre('cook', function(next) {123 this.waffles = false;124 next();125 });126 var obj = { bacon: 0, eggs: 0 };127 hooks.execPre('cook', obj, function() {128 assert.equal(3, obj.bacon);129 assert.equal(4, obj.eggs);130 assert.equal(false, obj.waffles);131 // acquit:ignore:start132 done();133 // acquit:ignore:end134 });135 });136 /* You can also return a promise from your pre hooks instead of calling137 * `next()`. When the returned promise resolves, kareem will kick off the138 * next middleware.139 */140 it('supports returning a promise', function(done) {141 hooks.pre('cook', function() {142 return new Promise(resolve => {143 setTimeout(() => {144 this.bacon = 3;145 resolve();146 }, 100);147 });148 });149 var obj = { bacon: 0 };150 hooks.execPre('cook', obj, function() {151 assert.equal(3, obj.bacon);152 // acquit:ignore:start153 done();154 // acquit:ignore:end155 });156 });157});158describe('post hooks', function() {159 var hooks;160 beforeEach(function() {161 hooks = new Kareem();162 });163 it('runs without any hooks specified', function(done) {164 hooks.execPost('cook', null, [1], function(error, eggs) {165 assert.ifError(error);166 assert.equal(1, eggs);167 done();168 });169 });170 it('executes with parameters passed in', function(done) {171 hooks.post('cook', function(eggs, bacon, callback) {172 assert.equal(1, eggs);173 assert.equal(2, bacon);174 callback();175 });176 hooks.execPost('cook', null, [1, 2], function(error, eggs, bacon) {177 assert.ifError(error);178 assert.equal(1, eggs);179 assert.equal(2, bacon);180 // acquit:ignore:start181 done();182 // acquit:ignore:end183 });184 });185 it('can use synchronous post hooks', function(done) {186 var execed = {};187 hooks.post('cook', function(eggs, bacon) {188 execed.first = true;189 assert.equal(1, eggs);190 assert.equal(2, bacon);191 });192 hooks.post('cook', function(eggs, bacon, callback) {193 execed.second = true;194 assert.equal(1, eggs);195 assert.equal(2, bacon);196 callback();197 });198 hooks.execPost('cook', null, [1, 2], function(error, eggs, bacon) {199 assert.ifError(error);200 assert.equal(2, Object.keys(execed).length);201 assert.ok(execed.first);202 assert.ok(execed.second);203 assert.equal(1, eggs);204 assert.equal(2, bacon);205 // acquit:ignore:start206 done();207 // acquit:ignore:end208 });209 });210 /* You can also return a promise from your post hooks instead of calling211 * `next()`. When the returned promise resolves, kareem will kick off the212 * next middleware.213 */214 it('supports returning a promise', function(done) {215 hooks.post('cook', function(bacon) {216 return new Promise(resolve => {217 setTimeout(() => {218 this.bacon = 3;219 resolve();220 }, 100);221 });222 });223 var obj = { bacon: 0 };224 hooks.execPost('cook', obj, obj, function() {225 assert.equal(obj.bacon, 3);226 // acquit:ignore:start227 done();228 // acquit:ignore:end229 });230 });231});232describe('wrap()', function() {233 var hooks;234 beforeEach(function() {235 hooks = new Kareem();236 });237 it('wraps pre and post calls into one call', function(done) {238 hooks.pre('cook', true, function(next, done) {239 this.bacon = 3;240 next();241 setTimeout(function() {242 done();243 }, 5);244 });245 hooks.pre('cook', true, function(next, done) {246 next();247 var _this = this;248 setTimeout(function() {249 _this.eggs = 4;250 done();251 }, 10);252 });253 hooks.pre('cook', function(next) {254 this.waffles = false;255 next();256 });257 hooks.post('cook', function(obj) {258 obj.tofu = 'no';259 });260 var obj = { bacon: 0, eggs: 0 };261 var args = [obj];262 args.push(function(error, result) {263 assert.ifError(error);264 assert.equal(null, error);265 assert.equal(3, obj.bacon);266 assert.equal(4, obj.eggs);267 assert.equal(false, obj.waffles);268 assert.equal('no', obj.tofu);269 assert.equal(obj, result);270 // acquit:ignore:start271 done();272 // acquit:ignore:end273 });274 hooks.wrap(275 'cook',276 function(o, callback) {277 assert.equal(3, obj.bacon);278 assert.equal(4, obj.eggs);279 assert.equal(false, obj.waffles);280 assert.equal(undefined, obj.tofu);281 callback(null, o);282 },283 obj,284 args);285 });286});287describe('createWrapper()', function() {288 var hooks;289 beforeEach(function() {290 hooks = new Kareem();291 });292 it('wraps wrap() into a callable function', function(done) {293 hooks.pre('cook', true, function(next, done) {294 this.bacon = 3;295 next();296 setTimeout(function() {297 done();298 }, 5);299 });300 hooks.pre('cook', true, function(next, done) {301 next();302 var _this = this;303 setTimeout(function() {304 _this.eggs = 4;305 done();306 }, 10);307 });308 hooks.pre('cook', function(next) {309 this.waffles = false;310 next();311 });312 hooks.post('cook', function(obj) {313 obj.tofu = 'no';314 });315 var obj = { bacon: 0, eggs: 0 };316 var cook = hooks.createWrapper(317 'cook',318 function(o, callback) {319 assert.equal(3, obj.bacon);320 assert.equal(4, obj.eggs);321 assert.equal(false, obj.waffles);322 assert.equal(undefined, obj.tofu);323 callback(null, o);324 },325 obj);326 cook(obj, function(error, result) {327 assert.ifError(error);328 assert.equal(3, obj.bacon);329 assert.equal(4, obj.eggs);330 assert.equal(false, obj.waffles);331 assert.equal('no', obj.tofu);332 assert.equal(obj, result);333 // acquit:ignore:start334 done();335 // acquit:ignore:end336 });337 });338});339describe('clone()', function() {340 it('clones a Kareem object', function() {341 var k1 = new Kareem();342 k1.pre('cook', function() {});343 k1.post('cook', function() {});344 var k2 = k1.clone();345 assert.deepEqual(Array.from(k2._pres.keys()), ['cook']);346 assert.deepEqual(Array.from(k2._posts.keys()), ['cook']);347 });348});349describe('merge()', function() {350 it('pulls hooks from another Kareem object', function() {351 var k1 = new Kareem();352 var test1 = function() {};353 k1.pre('cook', test1);354 k1.post('cook', function() {});355 var k2 = new Kareem();356 var test2 = function() {};357 k2.pre('cook', test2);358 var k3 = k2.merge(k1);359 assert.equal(k3._pres.get('cook').length, 2);360 assert.equal(k3._pres.get('cook')[0].fn, test2);361 assert.equal(k3._pres.get('cook')[1].fn, test1);362 assert.equal(k3._posts.get('cook').length, 1);363 });...
hookBuilder.ts
Source:hookBuilder.ts
1/** @module transition */ /** for typedoc */2import {IInjectable, extend, tail, assertPredicate, unnestR, flatten, identity} from "../common/common";3import {isArray} from "../common/predicates";4import {TransitionOptions, TransitionHookOptions, IHookRegistry, TreeChanges, IEventHook, ITransitionService, IMatchingNodes} from "./interface";5import {Transition, TransitionHook} from "./module";6import {State} from "../state/module";7import {Node} from "../path/module";8/**9 * This class returns applicable TransitionHooks for a specific Transition instance.10 *11 * Hooks (IEventHook) may be registered globally, e.g., $transitions.onEnter(...), or locally, e.g.12 * myTransition.onEnter(...). The HookBuilder finds matching IEventHooks (where the match criteria is13 * determined by the type of hook)14 *15 * The HookBuilder also converts IEventHooks objects to TransitionHook objects, which are used to run a Transition.16 *17 * The HookBuilder constructor is given the $transitions service and a Transition instance. Thus, a HookBuilder18 * instance may only be used for one specific Transition object. (side note: the _treeChanges accessor is private19 * in the Transition class, so we must also provide the Transition's _treeChanges)20 *21 */22export class HookBuilder {23 treeChanges: TreeChanges;24 transitionOptions: TransitionOptions;25 toState: State;26 fromState: State;27 constructor(private $transitions: ITransitionService, private transition: Transition, private baseHookOptions: TransitionHookOptions) {28 this.treeChanges = transition.treeChanges();29 this.toState = tail(this.treeChanges.to).state;30 this.fromState = tail(this.treeChanges.from).state;31 this.transitionOptions = transition.options();32 }33 // TODO: These get* methods are returning different cardinalities of hooks34 // onBefore/onStart/onFinish/onSuccess/onError returns an array of hooks35 // onExit/onRetain/onEnter returns an array of arrays of hooks36 getOnBeforeHooks = () => this._buildNodeHooks("onBefore", "to", tupleSort(), undefined, { async: false });37 getOnStartHooks = () => this._buildNodeHooks("onStart", "to", tupleSort());38 getOnExitHooks = () => this._buildNodeHooks("onExit", "exiting", tupleSort(true), (node) => ({ $state$: node.state }));39 getOnRetainHooks = () => this._buildNodeHooks("onRetain", "retained", tupleSort(), (node) => ({ $state$: node.state }));40 getOnEnterHooks = () => this._buildNodeHooks("onEnter", "entering", tupleSort(), (node) => ({ $state$: node.state }));41 getOnFinishHooks = () => this._buildNodeHooks("onFinish", "to", tupleSort(), (node) => ({ $treeChanges$: this.treeChanges }));42 getOnSuccessHooks = () => this._buildNodeHooks("onSuccess", "to", tupleSort(), undefined, {async: false, rejectIfSuperseded: false});43 getOnErrorHooks = () => this._buildNodeHooks("onError", "to", tupleSort(), undefined, {async: false, rejectIfSuperseded: false});44 asyncHooks() {45 let onStartHooks = this.getOnStartHooks();46 let onExitHooks = this.getOnExitHooks();47 let onRetainHooks = this.getOnRetainHooks();48 let onEnterHooks = this.getOnEnterHooks();49 let onFinishHooks = this.getOnFinishHooks();50 let asyncHooks = [onStartHooks, onExitHooks, onRetainHooks, onEnterHooks, onFinishHooks];51 return asyncHooks.reduce(unnestR, []).filter(identity);52 }53 /**54 * Returns an array of newly built TransitionHook objects.55 *56 * - Finds all IEventHooks registered for the given `hookType` which matched the transition's [[TreeChanges]].57 * - Finds [[Node]] (or `Node[]`) to use as the TransitionHook context(s)58 * - For each of the [[Node]]s, creates a TransitionHook59 *60 * @param hookType the name of the hook registration function, e.g., 'onEnter', 'onFinish'.61 * @param matchingNodesProp selects which [[Node]]s from the [[IMatchingNodes]] object to create hooks for.62 * @param getLocals a function which accepts a [[Node]] and returns additional locals to provide to the hook as injectables63 * @param sortHooksFn a function which compares two HookTuple and returns <1, 0, or >164 * @param options any specific Transition Hook Options65 */66 private _buildNodeHooks(hookType: string,67 matchingNodesProp: string,68 sortHooksFn: (l: HookTuple, r: HookTuple) => number,69 getLocals: (node: Node) => any = (node) => ({}),70 options: TransitionHookOptions = {}): TransitionHook[] {71 // Find all the matching registered hooks for a given hook type72 let matchingHooks = this._matchingHooks(hookType, this.treeChanges);73 if (!matchingHooks) return [];74 const makeTransitionHooks = (hook: IEventHook) => {75 // Fetch the Nodes that caused this hook to match.76 let matches: IMatchingNodes = hook.matches(this.treeChanges);77 // Select the Node[] that will be used as TransitionHook context objects78 let nodes: Node[] = matches[matchingNodesProp];79 // Return an array of HookTuples80 return nodes.map(node => {81 let _options = extend({ traceData: { hookType, context: node} }, this.baseHookOptions, options);82 let transitionHook = new TransitionHook(hook.callback, getLocals(node), node.resolveContext, _options);83 return <HookTuple> { hook, node, transitionHook };84 });85 };86 return matchingHooks.map(makeTransitionHooks)87 .reduce(unnestR, [])88 .sort(sortHooksFn)89 .map(tuple => tuple.transitionHook);90 }91 /**92 * Finds all IEventHooks from:93 * - The Transition object instance hook registry94 * - The TransitionService ($transitions) global hook registry95 *96 * which matched:97 * - the eventType98 * - the matchCriteria (to, from, exiting, retained, entering)99 *100 * @returns an array of matched [[IEventHook]]s101 */102 private _matchingHooks(hookName: string, treeChanges: TreeChanges): IEventHook[] {103 return [ this.transition, this.$transitions ] // Instance and Global hook registries104 .map((reg: IHookRegistry) => reg.getHooks(hookName)) // Get named hooks from registries105 .filter(assertPredicate(isArray, `broken event named: ${hookName}`)) // Sanity check106 .reduce(unnestR, []) // Un-nest IEventHook[][] to IEventHook[] array107 .filter(hook => hook.matches(treeChanges)); // Only those satisfying matchCriteria108 }109}110interface HookTuple { hook: IEventHook, node: Node, transitionHook: TransitionHook }111/**112 * A factory for a sort function for HookTuples.113 *114 * The sort function first compares the Node depth (how deep in the state tree a node is), then compares115 * the EventHook priority.116 *117 * @param reverseDepthSort a boolean, when true, reverses the sort order for the node depth118 * @returns a tuple sort function119 */120function tupleSort(reverseDepthSort = false) {121 return function nodeDepthThenPriority(l: HookTuple, r: HookTuple): number {122 let factor = reverseDepthSort ? -1 : 1;123 let depthDelta = (l.node.state.path.length - r.node.state.path.length) * factor;124 return depthDelta !== 0 ? depthDelta : r.hook.priority - l.hook.priority;125 }...
Using AI Code Generation
1import { MockBuilder, MockRender, ngMocks } from 'ng-mocks';2import { AppModule } from './app.module';3import { AppComponent } from './app.component';4describe('AppComponent', () => {5 beforeEach(() => MockBuilder(AppComponent, AppModule));6 it('should render title', () => {7 const fixture = MockRender(AppComponent);8 const title = ngMocks.find('h1');9 expect(title).toBeDefined();10 expect(title.nativeElement.textContent).toContain('Welcome to app!');11 });12});13import { Component } from '@angular/core';14import { MockBuilder, MockRender } from 'ng-mocks';15import { AppModule } from './app.module';16@Component({17})18export class AppComponent {19 title = 'app';20}21 Welcome to {{title}}!22import { NgModule } from '@angular/core';23import { BrowserModule } from '@angular/platform-browser';24import { AppComponent } from './app.component';25@NgModule({26 imports: [27})28export class AppModule { }
Using AI Code Generation
1import { MockBuilder, MockRender } from 'ng-mocks';2import { AppModule } from './app.module';3import { AppComponent } from './app.component';4describe('AppComponent', () => {5 beforeEach(() => MockBuilder(AppComponent).keep(AppModule));6 it('should create the app', () => {7 const fixture = MockRender(AppComponent);8 const app = fixture.point.componentInstance;9 expect(app).toBeTruthy();10 });11});
Using AI Code Generation
1import { TestBed } from '@angular/core/testing';2import { MockBuilder, MockRender } from 'ng-mocks';3import { AppComponent } from './app.component';4import { AppModule } from './app.module';5describe('AppComponent', () => {6 beforeEach(() => MockBuilder(AppComponent, AppModule));7 it('renders the component', () => {8 const fixture = MockRender(AppComponent);9 expect(fixture.nativeElement.innerHTML).toContain('Welcome to app!');10 });11});12import { Component } from '@angular/core';13@Component({14})15export class AppComponent {16 title = 'app';17}18import { NgModule } from '@angular/core';19import { BrowserModule } from '@angular/platform-browser';20import { AppComponent } from './app.component';21@NgModule({22 imports: [23})24export class AppModule { }25 Welcome to {{title}}!26/* :host {27 display: block;28} */29import { TestBed, async } from '@angular/core/testing';30import { AppComponent } from './app.component';31describe('AppComponent', () => {32 beforeEach(async(() => {33 TestBed.configureTestingModule({34 }).compileComponents();35 }));36 it('should create the app', () => {37 const fixture = TestBed.createComponent(AppComponent);38 const app = fixture.debugElement.componentInstance;39 expect(app).toBeTruthy();40 });41 it(`should have as title 'app'`, () => {42 const fixture = TestBed.createComponent(AppComponent);43 const app = fixture.debugElement.componentInstance;44 expect(app.title).toEqual('app');45 });46 it('should render title in a h1 tag', () => {47 const fixture = TestBed.createComponent(AppComponent);48 fixture.detectChanges();49 const compiled = fixture.debugElement.nativeElement;50 expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');51 });52});53module.exports = function (config) {
Using AI Code Generation
1import { MockBuilder, MockRender, MockedComponentFixture } from 'ng-mocks';2import { MyComponent } from './my.component';3describe('MyComponent', () => {4 let component: MyComponent;5 let fixture: MockedComponentFixture<MyComponent>;6 beforeEach(() => MockBuilder(MyComponent));7 beforeEach(() => {8 fixture = MockRender(MyComponent);9 component = fixture.point.componentInstance;10 });11 it('should create', () => {12 expect(component).toBeTruthy();13 });14});15import { Component, OnInit } from '@angular/core';16@Component({17})18export class MyComponent implements OnInit {19 constructor() { }20 ngOnInit() {21 }22}23import { async, ComponentFixture, TestBed } from '@angular/core/testing';24import { MyComponent } from './my.component';25describe('MyComponent', () => {26 let component: MyComponent;27 let fixture: ComponentFixture<MyComponent>;28 beforeEach(async(() => {29 TestBed.configureTestingModule({30 })31 .compileComponents();32 }));33 beforeEach(() => {34 fixture = TestBed.createComponent(MyComponent);35 component = fixture.componentInstance;36 fixture.detectChanges();37 });38 it('should create', () => {39 expect(component).toBeTruthy();40 });41});
Using AI Code Generation
1import { MockBuilder, MockRender } from 'ng-mocks';2beforeEach(() => MockBuilder(MyComponent));3it('renders the component', () => {4 const fixture = MockRender(MyComponent);5 expect(fixture.point.componentInstance).toBeTruthy();6});7import { MockBuilder, MockRender, MockInstance } from 'ng-mocks';8beforeEach(() => MockBuilder(MyComponent));9it('renders the component', () => {10 MockInstance(MyService, {11 getItems: () => ['item1', 'item2', 'item3'],12 });13 const fixture = MockRender(MyComponent);14 expect(fixture.point.componentInstance).toBeTruthy();15});16import { MockBuilder, MockRender, MockPipe } from 'ng-mocks';17beforeEach(() => MockBuilder(MyComponent));18it('renders the component', () => {19 MockPipe(MyPipe, () => 'mocked value');20 const fixture = MockRender(MyComponent);21 expect(fixture.point.componentInstance).toBeTruthy();22});23import { MockBuilder, MockRender, MockDirective } from 'ng-mocks';24beforeEach(() => MockBuilder(MyComponent));25it('renders the component', () => {26 MockDirective(MyDirective);27 const fixture = MockRender(MyComponent);28 expect(fixture.point.componentInstance).toBeTruthy();29});
Using AI Code Generation
1import { MockBuilder, MockRender, ngMocks } from 'ng-mocks';2describe('test', () => {3 beforeEach(() => MockBuilder(TestComponent));4 beforeEach(() => MockRender(TestComponent));5 it('should test', () => {6 const component = ngMocks.findInstance(TestComponent);7 expect(component).toBeDefined();8 });9});10import { TestBed } from '@angular/core/testing';11import { MockBuilder, MockRender, ngMocks } from 'ng-mocks';12describe('test', () => {13 beforeEach(() => MockBuilder(TestComponent));14 beforeEach(() => MockRender(TestComponent));15 it('should test', () => {16 const component = ngMocks.findInstance(TestComponent);17 expect(component).toBeDefined();18 });19});20import { TestBed } from '@angular/core/testing';21import { MockBuilder, MockRender, ngMocks } from 'ng-mocks';22describe('test', () => {23 beforeEach(() => MockBuilder(TestComponent));24 beforeEach(() => MockRender(TestComponent));25 it('should test', () => {26 const component = ngMocks.findInstance(TestComponent);27 expect(component).toBeDefined();28 });29});30import { TestBed
Using AI Code Generation
1import { MockBuilder, MockRender, ngMocks } from 'ng-mocks';2describe('MockBuilder', () => {3 beforeEach(() => MockBuilder(TestComponent));4 it('should render', () => {5 const fixture = MockRender(TestComponent);6 const component = ngMocks.findInstance(TestComponent);7 const element = ngMocks.find('test-component');8 const debugElement = ngMocks.find('test-component');9 });10});11import { MockBuilder, MockRender, ngMocks } from 'ng-mocks';12describe('MockInstance', () => {13 beforeEach(() => MockBuilder(TestComponent));14 it('should render', () => {15 const fixture = MockRender(TestComponent);16 const component = ngMocks.findInstance(TestComponent);17 const element = ngMocks.find('test-component');18 const debugElement = ngMocks.find('test-component');19 });20});21import { MockBuilder, MockRender, ngMocks } from 'ng-mocks';22describe('MockRender', () => {23 beforeEach(() => MockBuilder(TestComponent));24 it('should render', () => {25 const fixture = MockRender(TestComponent);26 const component = ngMocks.findInstance(TestComponent);27 const element = ngMocks.find('test-component');
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!