import HotTable from '../src/HotTable.vue'; import HotColumn from '../src/HotColumn.vue'; import BaseEditorComponent from '../src/BaseEditorComponent.vue'; import { mount } from '@vue/test-utils'; import Vue from 'vue'; import { registerAllCellTypes } from 'handsontable/registry'; import { createDomContainer, createSampleData, mockClientDimensions } from './_helpers'; registerAllCellTypes(); describe('createColumnSettings', () => { it('should create the column settings based on the data provided to the `hot-column` component and its child components', () => { const dummyRendererComponent = { render: function (h) { return h('DIV', 'test-value'); } }; const dummyEditorComponent = { render: function (h) { return h(); }, data: function () { return { hotCustomEditorClass: class A { getValue() { return 'test-value-editor'; } } } } }; let App = Vue.extend({ render(h) { // HotTable return h(HotTable, { props: { data: createSampleData(1, 1), licenseKey: 'non-commercial-and-evaluation', autoRowSize: false, autoColumnSize: false, init: function () { mockClientDimensions(this.rootElement, 400, 400); } } }, [ // HotColumn #1 h(HotColumn, { props: { title: 'test-title' } }, [ h(dummyRendererComponent, { attrs: { 'hot-renderer': true } }), h(dummyEditorComponent, { attrs: { 'hot-editor': true } }) ]), // HotColumn #2 h(HotColumn, { props: { readOnly: true, type: 'numeric', renderer: function () { return 'test-value2'; } } }), // HotColumn #3 h(HotColumn, { props: { settings: { title: 'title-3', renderer: function () { return 'test-value3'; } }, readOnly: true } }) ]) } }); let testWrapper = mount(App, { attachTo: createDomContainer() }); const hotTableComponent = testWrapper.vm.$children[0]; expect(hotTableComponent.columnSettings[0].title).toEqual('test-title'); expect(hotTableComponent.columnSettings[0].renderer(hotTableComponent.hotInstance, document.createElement('TD')).innerHTML).toEqual('
test-value
'); expect((new hotTableComponent.columnSettings[0].editor()).getValue()).toEqual('test-value-editor'); expect(hotTableComponent.columnSettings[1].title).toEqual(void 0); expect(hotTableComponent.columnSettings[1].readOnly).toEqual(true); expect(hotTableComponent.columnSettings[1].type).toEqual('numeric'); expect(hotTableComponent.columnSettings[1].renderer()).toEqual('test-value2'); expect(hotTableComponent.columnSettings[2].title).toEqual('title-3'); expect(hotTableComponent.columnSettings[2].readOnly).toEqual(true); expect(hotTableComponent.columnSettings[2].renderer()).toEqual('test-value3'); expect(hotTableComponent.hotInstance.getSettings().columns[0].title).toEqual('test-title'); expect(hotTableComponent.hotInstance.getSettings().columns[0].renderer(hotTableComponent.hotInstance, document.createElement('TD')).innerHTML).toEqual('
test-value
'); expect((new (hotTableComponent.hotInstance.getSettings().columns[0].editor)()).getValue()).toEqual('test-value-editor'); expect(hotTableComponent.hotInstance.getSettings().columns[1].title).toEqual(void 0); expect(hotTableComponent.hotInstance.getSettings().columns[1].readOnly).toEqual(true); expect(hotTableComponent.hotInstance.getSettings().columns[1].type).toEqual('numeric'); expect(hotTableComponent.hotInstance.getSettings().columns[1].renderer()).toEqual('test-value2'); expect(hotTableComponent.hotInstance.getSettings().columns[2].title).toEqual('title-3'); expect(hotTableComponent.hotInstance.getSettings().columns[2].readOnly).toEqual(true); expect(hotTableComponent.hotInstance.getSettings().columns[2].renderer()).toEqual('test-value3'); testWrapper.destroy(); }); }); describe('renderer cache', () => { it('should cache the same amount of cells, as they are in the table (below LRU limit)', () => { const dummyRendererComponent = { render: function (h) { return h(); } }; let App = Vue.extend({ render(h) { // HotTable return h(HotTable, { props: { data: createSampleData(20, 2), width: 400, height: 400, licenseKey: 'non-commercial-and-evaluation', autoRowSize: false, autoColumnSize: false, init: function () { mockClientDimensions(this.rootElement, 400, 400); } } }, [ // HotColumn #1 h(HotColumn, { props: {} }, [ h(dummyRendererComponent, { attrs: { 'hot-renderer': true } }) ]), // HotColumn #2 h(HotColumn, { props: {} }, [ h(dummyRendererComponent, { attrs: { 'hot-renderer': true } }) ]) ]) } }); let testWrapper = mount(App, { attachTo: createDomContainer() }); const hotTableComponent = testWrapper.vm.$children[0]; expect(hotTableComponent.rendererCache.size).toEqual(40); testWrapper.destroy(); }); it('should cache the maximum amount of cells possible in the LRU map, if the number of cells exceeds this limit', () => { const dummyRendererComponent = { render: function (h) { return h(); } }; let App = Vue.extend({ render(h) { // HotTable return h(HotTable, { props: { data: createSampleData(200, 2), width: 400, height: 400, licenseKey: 'non-commercial-and-evaluation', autoRowSize: false, autoColumnSize: false, init: function () { mockClientDimensions(this.rootElement, 400, 400); }, wrapperRendererCacheSize: 100 } }, [ // HotColumn #1 h(HotColumn, { props: {} }, [ h(dummyRendererComponent, { attrs: { 'hot-renderer': true } }) ]), // HotColumn #2 h(HotColumn, { props: {} }, [ h(dummyRendererComponent, { attrs: { 'hot-renderer': true } }) ]) ]) } }); let testWrapper = mount(App, { attachTo: createDomContainer() }); const hotTableComponent = testWrapper.vm.$children[0]; expect(hotTableComponent.rendererCache.size).toEqual(100); testWrapper.destroy(); }); }); describe('hot-column children', () => { it('should add as many hot-column children as there are cached renderers and editors for that column', () => { const dummyRendererComponent = { render: function (h) { return h(); } }; const dummyEditorComponent = { render: function (h) { return h(); } }; let App = Vue.extend({ render(h) { // HotTable return h(HotTable, { props: { data: createSampleData(50, 2), width: 400, height: 400, licenseKey: 'non-commercial-and-evaluation', autoRowSize: false, autoColumnSize: false, init: function () { mockClientDimensions(this.rootElement, 400, 400); } } }, [ // HotColumn #1 h(HotColumn, { props: {} }, [ h(dummyRendererComponent, { attrs: { 'hot-renderer': true } }), h(dummyEditorComponent, { attrs: { 'hot-editor': true } }) ]), // HotColumn #2 h(HotColumn, { props: {} }, [ h(dummyRendererComponent, { attrs: { 'hot-renderer': true } }) ]) ]) } }); let testWrapper = mount(App, { attachTo: createDomContainer() }); const hotTableComponent = testWrapper.vm.$children[0]; expect(hotTableComponent.rendererCache.size).toEqual(100); expect(hotTableComponent.$children[0].$children.length).toEqual(51); expect(hotTableComponent.$children[1].$children.length).toEqual(50); testWrapper.destroy(); }); it('should be possible to set a key on custom editor to use the same component twice', () => { const dummyEditorComponent = Vue.component('renderer-component', { name: 'EditorComponent', extends: BaseEditorComponent, props: ['test-prop'], render: function (h) { return h('div', {}); } }); let App = Vue.extend({ render(h) { // HotTable return h(HotTable, { props: { data: createSampleData(2, 2), licenseKey: 'non-commercial-and-evaluation', } }, [ h(HotColumn, {}, [ h(dummyEditorComponent, { key: 'editor-one', attrs: { 'hot-editor': true, 'test-prop': 'test-prop-value-1' } }), ]), h(HotColumn, {}, [ h(dummyEditorComponent, { key: 'editor-two', attrs: { 'hot-editor': true, 'test-prop': 'test-prop-value-2' } }) ]) ]) } }); let testWrapper = mount(App, { attachTo: createDomContainer() }); const hotTableComponent = testWrapper.vm.$children[0]; expect(hotTableComponent.editorCache.get('EditorComponent:editor-one').$props.testProp).toEqual('test-prop-value-1'); expect(hotTableComponent.editorCache.get('EditorComponent:editor-two').$props.testProp).toEqual('test-prop-value-2'); testWrapper.destroy(); }); it('should be possible to set a key on custom editor to use the same component twice, alongside an editor without' + ' the key property defined', () => { const dummyEditorComponent = Vue.component('renderer-component', { name: 'EditorComponent', extends: BaseEditorComponent, props: ['test-prop'], methods: { getValue: function () { // For the sake of this test, the returned value is the passed test prop return this.$props.testProp; }, setValue: () => {}, open: () => {} }, render: function (h) { return h('div', {}); } }); let App = Vue.extend({ render(h) { // HotTable return h(HotTable, { props: { data: createSampleData(2, 2), licenseKey: 'non-commercial-and-evaluation', } }, [ h(HotColumn, {}, [ h(dummyEditorComponent, { key: 'editor-one', attrs: { 'hot-editor': true, 'test-prop': 'test-prop-value-1' } }), ]), h(HotColumn, {}, [ h(dummyEditorComponent, { key: 'editor-two', attrs: { 'hot-editor': true, 'test-prop': 'test-prop-value-2' } }) ]), h(HotColumn, {}, [ h(dummyEditorComponent, { attrs: { 'hot-editor': true, 'test-prop': 'test-prop-value-common' } }) ]), h(HotColumn, {}, [ h(dummyEditorComponent, { attrs: { 'hot-editor': true, } }) ]) ]) } }); let testWrapper = mount(App, { attachTo: createDomContainer() }); const hotTableComponent = testWrapper.vm.$children[0]; expect(hotTableComponent.editorCache.get('EditorComponent:editor-one').$props.testProp).toEqual('test-prop-value-1'); expect(hotTableComponent.editorCache.get('EditorComponent:editor-two').$props.testProp).toEqual('test-prop-value-2'); expect(hotTableComponent.editorCache.get('EditorComponent').$props.testProp).toEqual('test-prop-value-common'); const hotInstance = hotTableComponent.hotInstance; expect(hotInstance.getCellEditor(0, 0).prototype.getValue()).toEqual('test-prop-value-1'); expect(hotInstance.getCellEditor(0, 1).prototype.getValue()).toEqual('test-prop-value-2'); expect(hotInstance.getCellEditor(0, 2).prototype.getValue()).toEqual('test-prop-value-common'); expect(hotInstance.getCellEditor(0, 3).prototype.getValue()).toEqual('test-prop-value-common'); testWrapper.destroy(); }); });