<NME> hotTableHelpers.spec.ts
<BEF> import {
  rewriteSettings,
  prepareSettings,
  propFactory,
  propWatchFactory
} from '../src/helpers';

describe('rewriteSettings', () => {
  it('should rewrite the settings element passed to the watchers to be a clean object prepared to use withing Handsontable config, when the input element is an object', () => {
    const fakeWatcher = () => {};
    fakeWatcher.prototype.sampleMethod = () => {};
    fakeWatcher.prototype.sampleProperty = null;

    const fakeWatcherInstance = new fakeWatcher();
    fakeWatcherInstance.testedProperty = null;
    fakeWatcherInstance.testedMethod = () => {};

    expect(typeof fakeWatcherInstance.sampleMethod).toEqual('function');
    expect(typeof fakeWatcherInstance.testedMethod).toEqual('function');
    expect(fakeWatcherInstance.sampleProperty).toEqual(null);
    expect(fakeWatcherInstance.testedProperty).toEqual(null);

    let cleanObject: any = rewriteSettings(fakeWatcherInstance);

    expect(typeof cleanObject.sampleMethod).toEqual('undefined');
    expect(typeof cleanObject.testedMethod).toEqual('function');
    expect(cleanObject.sampleProperty).toEqual(void 0);
    expect(cleanObject.testedProperty).toEqual(null);
    expect(Object.prototype.toString.call(cleanObject)).toEqual('[object Object]');
  });
});

describe('propFactory', () => {
  it('should generate an object containing all the available Handsontable properties and plugin hooks', () => {
    const props: any = propFactory('HotTable');

    expect(typeof props.startRows).toEqual('object');
    expect(typeof props.startCols).toEqual('object');
    expect(typeof props.data).toEqual('object');
    expect(typeof props.fixedRowsTop).toEqual('object');
    expect(typeof props.afterCreateRow).toEqual('object');
    expect(typeof props.afterGetCellMeta).toEqual('object');
    expect(typeof props.beforeInit).toEqual('object');
    expect(typeof props.randomProp).toEqual('undefined');
  });
});

describe('propWatchFactory', () => {
  it('should generate and object containing all the available Handsontable properties and hooks tied to the Handsontable updating function', () => {
    const bulkUpdateFunction = () => {};
    const props: any = propWatchFactory(bulkUpdateFunction);

    expect(typeof props.startRows).toEqual('object');
    expect(typeof props.startRows.handler).toEqual('function');
    expect(props.startRows.toString().indexOf('bulkUpdateFunction') > -1).toBe(false);
    expect(typeof props.startCols).toEqual('object');
    expect(typeof props.startCols.handler).toEqual('function');
    expect(props.startCols.toString().indexOf('bulkUpdateFunction') > -1).toBe(false);
    expect(typeof props.data).toEqual('object');
    expect(typeof props.data.handler).toEqual('function');
    expect(props.data.toString().indexOf('bulkUpdateFunction') > -1).toBe(false);
    expect(typeof props.fixedRowsTop).toEqual('object');
    expect(typeof props.fixedRowsTop.handler).toEqual('function');
    expect(props.fixedRowsTop.toString().indexOf('bulkUpdateFunction') > -1).toBe(false);
    expect(typeof props.afterCreateRow).toEqual('object');
    expect(typeof props.afterCreateRow.handler).toEqual('function');
    expect(props.afterCreateRow.toString().indexOf('bulkUpdateFunction') > -1).toBe(false);
    expect(typeof props.afterGetCellMeta).toEqual('object');
    expect(typeof props.afterGetCellMeta.handler).toEqual('function');
    expect(props.afterGetCellMeta.toString().indexOf('bulkUpdateFunction') > -1).toBe(false);
    expect(typeof props.beforeInit).toEqual('object');
    expect(typeof props.beforeInit.handler).toEqual('function');
    expect(props.beforeInit.toString().indexOf('bulkUpdateFunction') > -1).toBe(false);
    expect(typeof props.randomProp).toEqual('undefined');
  });
});

describe('prepareSettings', () => {
  it('should prepare the settings object to be used with Handsontable', () => {
    const onPrefixedPropObj = {
      'afterChange': {},
      'afterCellMetaReset': {},
      'afterChangesObserved': {},
      'afterContextMenuDefaultOptions': {},
      'beforeContextMenuSetItems': {},
      'afterDropdownMenuDefaultOptions': {},
      'beforeDropdownMenuSetItems': {},
      'afterContextMenuHide': {},
      'afterContextMenuShow': {},
      'afterCopyLimit': {},
      'beforeCreateCol': {},
      'afterCreateCol': {},
      'beforeCreateRow': {},
      'afterCreateRow': {}
    };

    const result: any = prepareSettings(onPrefixedPropObj);

    expect(typeof result.afterChange).toEqual('object');
    expect(typeof result.afterCellMetaReset).toEqual('object');
    expect(typeof result.afterChangesObserved).toEqual('object');
    expect(typeof result.afterContextMenuDefaultOptions).toEqual('object');
    expect(typeof result.beforeContextMenuSetItems).toEqual('object');
    expect(typeof result.afterDropdownMenuDefaultOptions).toEqual('object');
    expect(typeof result.beforeDropdownMenuSetItems).toEqual('object');
    expect(typeof result.afterContextMenuHide).toEqual('object');
    expect(typeof result.afterContextMenuShow).toEqual('object');
    expect(typeof result.afterCopyLimit).toEqual('object');
    expect(typeof result.beforeCreateCol).toEqual('object');
    expect(typeof result.afterCreateCol).toEqual('object');
    expect(typeof result.beforeCreateRow).toEqual('object');
    expect(typeof result.afterCreateRow).toEqual('object');

    expect(typeof result.randomPropName).toEqual('undefined');
  });

  it('should prepare the settings object to be used with Handsontable (when two objects are provided)', () => {
    const onPrefixedPropObj = {
      'afterChange': {},
      'afterCellMetaReset': {},
      'afterChangesObserved': {},
      'afterContextMenuDefaultOptions': {},
      'beforeContextMenuSetItems': {},
      'afterDropdownMenuDefaultOptions': {},
      'beforeDropdownMenuSetItems': {},
      'afterContextMenuHide': {}
    };

    const secondOnPrefixedPropObj = {
      'afterContextMenuHide': {},
      'afterContextMenuShow': {},
      'afterCopyLimit': {},
      'beforeCreateCol': {},
      'afterCreateCol': {},
      'beforeCreateRow': {},
      'afterCreateRow': {}
    };

    const result: any = prepareSettings(onPrefixedPropObj, secondOnPrefixedPropObj);

    expect(typeof result.afterChange).toEqual('object');
    expect(typeof result.afterCellMetaReset).toEqual('object');
    expect(typeof result.afterChangesObserved).toEqual('object');
    expect(typeof result.afterContextMenuDefaultOptions).toEqual('object');
    expect(typeof result.beforeContextMenuSetItems).toEqual('object');
    expect(typeof result.afterDropdownMenuDefaultOptions).toEqual('object');
    expect(typeof result.beforeDropdownMenuSetItems).toEqual('object');
    expect(typeof result.afterContextMenuHide).toEqual('object');
    expect(typeof result.afterContextMenuShow).toEqual('object');
    expect(typeof result.afterCopyLimit).toEqual('object');
    expect(typeof result.beforeCreateCol).toEqual('object');
    expect(typeof result.afterCreateCol).toEqual('object');
    expect(typeof result.beforeCreateRow).toEqual('object');
    expect(typeof result.afterCreateRow).toEqual('object');

    expect(typeof result.randomPropName).toEqual('undefined');
  });
});

<MSG> Feature/issue 108 (#125)

* Add the HotColumn component to be used as a child of HotTable to define the column settings. [WIP]

* Fill missing typings.

* Update package-lock.

* Add additional tests.

* Add $router and $store tests + move cache to the HotTable class.

* Fix tests

* Specify additional types.

* Prevent throwing the license key warning in the tests.

* Change the renderer cache type to LRU Map, add tests for the renderer cache.

* Update parts of the test cases to use '@vue/test-utils'

* Fix a problem with HotColumn overwriting the settings passed to HotTable.

* Add 'Symbol' as a possible default value for the 'settings' prop + prevent the test cases from throwing warnings about auto column/row size.

* Remove misleading 'settings' and hook type declarations.

* Don't re-render the TD's contents if it's already rendererd in the viewport.

* Add a base editor component for vue components to extend.

* Rewrite the BaseVueHotEditor to a class.

* Fix tests.

* Update package-lock.

* Make hot-column inject `isRenderer` and `isEditor` properties to the renderer/editor components.

* Add a possibility to declare global editors/renderers as components.

* Add a possibility do set the column settings using a 'settings' prop on 'hot-column'.

* Change where isEditor prop is injected, correct tests etc.

* Correct typo.

* Bump the dependencies to the latest versions.

* Post CR updates:
- rename BaseVueHotEditor to BaseEditorComponent
- make editor components mount into #vueHotEditors element in DOM
- destroy the initial global editors/renderers

* Rename the editor container to `vueHotComponents`, because both editors and renderers are being mounter there (the renderers are later moved to the table cells).

* - Remove the prop watcher in favor of a auto-updating computed property
- Group updated props and call updateSettings only once
- Update only the props that needs to be updated

* Post-merge fixes

* Simplify the code a little.

* Watcher code cleanup.

<DFF> @@ -1,8 +1,7 @@
 import {
   rewriteSettings,
   prepareSettings,
-  propFactory,
-  propWatchFactory
+  propFactory
 } from '../src/helpers';
 
 describe('rewriteSettings', () => {
@@ -45,114 +44,30 @@ describe('propFactory', () => {
   });
 });
 
-describe('propWatchFactory', () => {
-  it('should generate and object containing all the available Handsontable properties and hooks tied to the Handsontable updating function', () => {
-    const bulkUpdateFunction = () => {};
-    const props: any = propWatchFactory(bulkUpdateFunction);
-
-    expect(typeof props.startRows).toEqual('object');
-    expect(typeof props.startRows.handler).toEqual('function');
-    expect(props.startRows.toString().indexOf('bulkUpdateFunction') > -1).toBe(false);
-    expect(typeof props.startCols).toEqual('object');
-    expect(typeof props.startCols.handler).toEqual('function');
-    expect(props.startCols.toString().indexOf('bulkUpdateFunction') > -1).toBe(false);
-    expect(typeof props.data).toEqual('object');
-    expect(typeof props.data.handler).toEqual('function');
-    expect(props.data.toString().indexOf('bulkUpdateFunction') > -1).toBe(false);
-    expect(typeof props.fixedRowsTop).toEqual('object');
-    expect(typeof props.fixedRowsTop.handler).toEqual('function');
-    expect(props.fixedRowsTop.toString().indexOf('bulkUpdateFunction') > -1).toBe(false);
-    expect(typeof props.afterCreateRow).toEqual('object');
-    expect(typeof props.afterCreateRow.handler).toEqual('function');
-    expect(props.afterCreateRow.toString().indexOf('bulkUpdateFunction') > -1).toBe(false);
-    expect(typeof props.afterGetCellMeta).toEqual('object');
-    expect(typeof props.afterGetCellMeta.handler).toEqual('function');
-    expect(props.afterGetCellMeta.toString().indexOf('bulkUpdateFunction') > -1).toBe(false);
-    expect(typeof props.beforeInit).toEqual('object');
-    expect(typeof props.beforeInit.handler).toEqual('function');
-    expect(props.beforeInit.toString().indexOf('bulkUpdateFunction') > -1).toBe(false);
-    expect(typeof props.randomProp).toEqual('undefined');
-  });
-});
-
 describe('prepareSettings', () => {
-  it('should prepare the settings object to be used with Handsontable', () => {
-    const onPrefixedPropObj = {
-      'afterChange': {},
-      'afterCellMetaReset': {},
-      'afterChangesObserved': {},
-      'afterContextMenuDefaultOptions': {},
-      'beforeContextMenuSetItems': {},
-      'afterDropdownMenuDefaultOptions': {},
-      'beforeDropdownMenuSetItems': {},
-      'afterContextMenuHide': {},
-      'afterContextMenuShow': {},
-      'afterCopyLimit': {},
-      'beforeCreateCol': {},
-      'afterCreateCol': {},
-      'beforeCreateRow': {},
-      'afterCreateRow': {}
+  it('should prepare the settings passed to the component props to be used within Handsontable', () => {
+    const propsMock = {
+      id: 'hot-id',
+      readOnly: true,
+      colHeaders: true,
+      afterChange: () => 'afterChangeResult',
+      settings: {
+        rowHeaders: true,
+        data: [[1, 2], [3, 4]],
+        afterUpdateSettings: () => 'afterUpdateSettingsResult'
+      }
     };
 
-    const result: any = prepareSettings(onPrefixedPropObj);
-
-    expect(typeof result.afterChange).toEqual('object');
-    expect(typeof result.afterCellMetaReset).toEqual('object');
-    expect(typeof result.afterChangesObserved).toEqual('object');
-    expect(typeof result.afterContextMenuDefaultOptions).toEqual('object');
-    expect(typeof result.beforeContextMenuSetItems).toEqual('object');
-    expect(typeof result.afterDropdownMenuDefaultOptions).toEqual('object');
-    expect(typeof result.beforeDropdownMenuSetItems).toEqual('object');
-    expect(typeof result.afterContextMenuHide).toEqual('object');
-    expect(typeof result.afterContextMenuShow).toEqual('object');
-    expect(typeof result.afterCopyLimit).toEqual('object');
-    expect(typeof result.beforeCreateCol).toEqual('object');
-    expect(typeof result.afterCreateCol).toEqual('object');
-    expect(typeof result.beforeCreateRow).toEqual('object');
-    expect(typeof result.afterCreateRow).toEqual('object');
-
-    expect(typeof result.randomPropName).toEqual('undefined');
-  });
-
-  it('should prepare the settings object to be used with Handsontable (when two objects are provided)', () => {
-    const onPrefixedPropObj = {
-      'afterChange': {},
-      'afterCellMetaReset': {},
-      'afterChangesObserved': {},
-      'afterContextMenuDefaultOptions': {},
-      'beforeContextMenuSetItems': {},
-      'afterDropdownMenuDefaultOptions': {},
-      'beforeDropdownMenuSetItems': {},
-      'afterContextMenuHide': {}
-    };
-
-    const secondOnPrefixedPropObj = {
-      'afterContextMenuHide': {},
-      'afterContextMenuShow': {},
-      'afterCopyLimit': {},
-      'beforeCreateCol': {},
-      'afterCreateCol': {},
-      'beforeCreateRow': {},
-      'afterCreateRow': {}
-    };
-
-    const result: any = prepareSettings(onPrefixedPropObj, secondOnPrefixedPropObj);
-
-    expect(typeof result.afterChange).toEqual('object');
-    expect(typeof result.afterCellMetaReset).toEqual('object');
-    expect(typeof result.afterChangesObserved).toEqual('object');
-    expect(typeof result.afterContextMenuDefaultOptions).toEqual('object');
-    expect(typeof result.beforeContextMenuSetItems).toEqual('object');
-    expect(typeof result.afterDropdownMenuDefaultOptions).toEqual('object');
-    expect(typeof result.beforeDropdownMenuSetItems).toEqual('object');
-    expect(typeof result.afterContextMenuHide).toEqual('object');
-    expect(typeof result.afterContextMenuShow).toEqual('object');
-    expect(typeof result.afterCopyLimit).toEqual('object');
-    expect(typeof result.beforeCreateCol).toEqual('object');
-    expect(typeof result.afterCreateCol).toEqual('object');
-    expect(typeof result.beforeCreateRow).toEqual('object');
-    expect(typeof result.afterCreateRow).toEqual('object');
-
-    expect(typeof result.randomPropName).toEqual('undefined');
+    const preparedSettings = prepareSettings(propsMock);
+
+    expect(preparedSettings.readOnly).toBe(true);
+    expect(preparedSettings.colHeaders).toBe(true);
+    expect(preparedSettings.rowHeaders).toBe(true);
+    expect(preparedSettings.data).toEqual([[1, 2], [3, 4]]);
+    expect(preparedSettings.afterUpdateSettings()).toBe('afterUpdateSettingsResult');
+    expect(preparedSettings.afterChange()).toBe('afterChangeResult');
+    expect(preparedSettings.id).toBe(void 0);
+    expect(preparedSettings.settings).toBe(void 0);
+    expect(preparedSettings.wrapperRendererCacheSize).toBe(void 0);
   });
 });

Feature/issue 108 (#125)