diff --git a/karma.conf.js b/karma.conf.js index 2dd23ade0..64b4e5c9d 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -14,7 +14,10 @@ module.exports = function(config) { // } // } // }, - exclude: ["demo", "dist/ng"] // ignore dummy demo .ts files + exclude: ["demo", "dist/ng"], // ignore dummy demo .ts files + include: [ + "./spec/**/*-spec.ts" + ] }, // base path that will be used to resolve all patterns (eg. files, exclude) diff --git a/spec/gridstack-engine-spec.ts b/spec/gridstack-engine-spec.ts index 990cbcb43..63158a0de 100644 --- a/spec/gridstack-engine-spec.ts +++ b/spec/gridstack-engine-spec.ts @@ -8,8 +8,8 @@ describe('gridstack engine', function() { let e: any = GridStackEngine; let w: any = window; - let findNode = function(engine, id) { - return engine.nodes.find((i) => i.id === id); + let findNode = function(engine: GridStackEngine, id: string) { + return engine.nodes.find(i => i.id === id); }; it('should exist setup function.', function() { @@ -23,9 +23,9 @@ describe('gridstack engine', function() { engine = new GridStackEngine(); expect(engine.column).toEqual(12); expect(engine.float).toEqual(false); - expect(engine.maxRow).toEqual(undefined); + expect(engine.maxRow).toEqual(undefined!); expect(engine.nodes).toEqual([]); - expect(engine.batchMode).toEqual(undefined); + expect(engine.batchMode).toEqual(undefined!); expect((engine as any).onChange).toEqual(undefined); }); @@ -146,21 +146,21 @@ describe('gridstack engine', function() { beforeAll(function() { engine = new GridStackEngine({float:true}); engine.nodes = [ - engine.prepareNode({x: 0, y: 0, id: 1, _dirty: true}), - engine.prepareNode({x: 3, y: 2, w: 3, h: 2, id: 2, _dirty: true}), - engine.prepareNode({x: 3, y: 7, w: 3, h: 2, id: 3}) + engine.prepareNode({x: 0, y: 0, id: "1", _dirty: true}), + engine.prepareNode({x: 3, y: 2, w: 3, h: 2, id: "2", _dirty: true}), + engine.prepareNode({x: 3, y: 7, w: 3, h: 2, id: "3"}) ]; }); beforeEach(function() { - delete engine.batchMode; + delete (engine as any).batchMode; }); it('should return all dirty nodes', function() { let nodes = engine.getDirtyNodes(); expect(nodes.length).toEqual(2); - expect(nodes[0].id).toEqual(1); - expect(nodes[1].id).toEqual(2); + expect(nodes[0].id).toEqual("1"); + expect(nodes[1].id).toEqual("2"); }); it('should\'n clean nodes if batchMode true', function() { @@ -230,9 +230,9 @@ describe('gridstack engine', function() { spyOn(spy, 'callback'); engine = new GridStackEngine({float:true, onChange: spy.callback}); engine.nodes = [ - engine.prepareNode({x: 0, y: 0, id: 1, _dirty: true}), - engine.prepareNode({x: 3, y: 2, w: 3, h: 2, id: 2, _dirty: true}), - engine.prepareNode({x: 3, y: 7, w: 3, h: 2, id: 3}) + engine.prepareNode({x: 0, y: 0, id: "1", _dirty: true}), + engine.prepareNode({x: 3, y: 2, w: 3, h: 2, id: "2", _dirty: true}), + engine.prepareNode({x: 3, y: 7, w: 3, h: 2, id: "3"}) ]; }); @@ -262,50 +262,50 @@ describe('gridstack engine', function() { it('shouldn\'t pack one node with y coord eq 0', function() { engine.nodes = [ - {x: 0, y: 0, w:1, h:1, id: 1}, + {x: 0, y: 0, w:1, h:1, id: "1"}, ]; (engine as any)._packNodes(); - expect(findNode(engine, 1)).toEqual(jasmine.objectContaining({x: 0, y: 0, h: 1})); - expect(findNode(engine, 1)._dirty).toBeFalsy(); + expect(findNode(engine, "1")).toEqual(jasmine.objectContaining({x: 0, y: 0, h: 1})); + expect(findNode(engine, "1")!._dirty).toBeFalsy(); }); it('should pack one node correctly', function() { engine.nodes = [ - {x: 0, y: 1, w:1, h:1, id: 1}, + {x: 0, y: 1, w:1, h:1, id: "1"}, ]; (engine as any)._packNodes(); - expect(findNode(engine, 1)).toEqual(jasmine.objectContaining({x: 0, y: 0, _dirty: true})); + expect(findNode(engine, "1")).toEqual(jasmine.objectContaining({x: 0, y: 0, _dirty: true})); }); it('should pack nodes correctly', function() { engine.nodes = [ - {x: 0, y: 1, w:1, h:1, id: 1}, - {x: 0, y: 5, w:1, h:1, id: 2}, + {x: 0, y: 1, w:1, h:1, id: "1"}, + {x: 0, y: 5, w:1, h:1, id: "2"}, ]; (engine as any)._packNodes(); - expect(findNode(engine, 1)).toEqual(jasmine.objectContaining({x: 0, y: 0, _dirty: true})); - expect(findNode(engine, 2)).toEqual(jasmine.objectContaining({x: 0, y: 1, _dirty: true})); + expect(findNode(engine, "1")).toEqual(jasmine.objectContaining({x: 0, y: 0, _dirty: true})); + expect(findNode(engine, "2")).toEqual(jasmine.objectContaining({x: 0, y: 1, _dirty: true})); }); it('should pack nodes correctly', function() { engine.nodes = [ - {x: 0, y: 5, w:1, h:1, id: 1}, - {x: 0, y: 1, w:1, h:1, id: 2}, + {x: 0, y: 5, w:1, h:1, id: "1"}, + {x: 0, y: 1, w:1, h:1, id: "2"}, ]; (engine as any)._packNodes(); - expect(findNode(engine, 2)).toEqual(jasmine.objectContaining({x: 0, y: 0, _dirty: true})); - expect(findNode(engine, 1)).toEqual(jasmine.objectContaining({x: 0, y: 1, _dirty: true})); + expect(findNode(engine, "2")).toEqual(jasmine.objectContaining({x: 0, y: 0, _dirty: true})); + expect(findNode(engine, "1")).toEqual(jasmine.objectContaining({x: 0, y: 1, _dirty: true})); }); it('should respect locked nodes', function() { engine.nodes = [ - {x: 0, y: 1, w:1, h:1, id: 1, locked: true}, - {x: 0, y: 5, w:1, h:1, id: 2}, + {x: 0, y: 1, w:1, h:1, id: "1", locked: true}, + {x: 0, y: 5, w:1, h:1, id: "2"}, ]; (engine as any)._packNodes(); - expect(findNode(engine, 1)).toEqual(jasmine.objectContaining({x: 0, y: 1, h: 1})); - expect(findNode(engine, 1)._dirty).toBeFalsy(); - expect(findNode(engine, 2)).toEqual(jasmine.objectContaining({x: 0, y: 2, _dirty: true})); + expect(findNode(engine, "1")).toEqual(jasmine.objectContaining({x: 0, y: 1, h: 1})); + expect(findNode(engine, "1")!._dirty).toBeFalsy(); + expect(findNode(engine, "2")).toEqual(jasmine.objectContaining({x: 0, y: 2, _dirty: true})); }); }); }); @@ -342,31 +342,31 @@ describe('gridstack engine', function() { }); it('should add widgets around locked one', function() { let nodes: GridStackNode[] = [ - {x: 0, y: 1, w: 12, h: 1, locked: true, noMove: true, noResize: true, id: 0}, - {x: 1, y: 0, w: 2, h: 3, id: 1} + {x: 0, y: 1, w: 12, h: 1, locked: true, noMove: true, noResize: true, id: "0"}, + {x: 1, y: 0, w: 2, h: 3, id: "1"} ]; // add locked item engine.addNode(nodes[0]) - expect(findNode(engine, 0)).toEqual(jasmine.objectContaining({x: 0, y: 1, w: 12, h: 1, locked: true})); + expect(findNode(engine, "0")).toEqual(jasmine.objectContaining({x: 0, y: 1, w: 12, h: 1, locked: true})); // add item that moves past locked one engine.addNode(nodes[1]) - expect(findNode(engine, 0)).toEqual(jasmine.objectContaining({x: 0, y: 1, w: 12, h: 1, locked: true})); - expect(findNode(engine, 1)).toEqual(jasmine.objectContaining({x: 1, y: 2, h: 3})); + expect(findNode(engine, "0")).toEqual(jasmine.objectContaining({x: 0, y: 1, w: 12, h: 1, locked: true})); + expect(findNode(engine, "1")).toEqual(jasmine.objectContaining({x: 1, y: 2, h: 3})); // locked item can still be moved directly (what user does) - let node0 = findNode(engine, 0); - expect(engine.moveNode(node0, {y:6})).toEqual(true); - expect(findNode(engine, 0)).toEqual(jasmine.objectContaining({x: 0, y: 6, h: 1, locked: true})); + let node0 = findNode(engine, "0"); + expect(engine.moveNode(node0!, {y:6})).toEqual(true); + expect(findNode(engine, "0")).toEqual(jasmine.objectContaining({x: 0, y: 6, h: 1, locked: true})); // but moves regular one past it - let node1 = findNode(engine, 1); - expect(engine.moveNode(node1, {x:6, y:6})).toEqual(true); + let node1 = findNode(engine, "1"); + expect(engine.moveNode(node1!, {x:6, y:6})).toEqual(true); expect(node1).toEqual(jasmine.objectContaining({x: 6, y: 7, w: 2, h: 3})); // but moves regular one before (gravity ON) engine.float = false; - expect(engine.moveNode(node1, {x:7, y:3})).toEqual(true); + expect(engine.moveNode(node1!, {x:7, y:3})).toEqual(true); expect(node1).toEqual(jasmine.objectContaining({x: 7, y: 0, w: 2, h: 3})); // but moves regular one before (gravity OFF) engine.float = true; - expect(engine.moveNode(node1, {x:7, y:3})).toEqual(true); + expect(engine.moveNode(node1!, {x:7, y:3})).toEqual(true); expect(node1).toEqual(jasmine.objectContaining({x: 7, y: 3, w: 2, h: 3})); }); }); diff --git a/spec/gridstack-spec.ts b/spec/gridstack-spec.ts index 534ebe6db..76455aef3 100644 --- a/spec/gridstack-spec.ts +++ b/spec/gridstack-spec.ts @@ -330,7 +330,7 @@ describe('gridstack', function() { expect(parseInt(el2.getAttribute('gs-h'))).toBe(4); // add default 1x1 item to the end (1 column) - let el3 = grid.addWidget(); + let el3 = grid.addWidget({ }); expect(el3).not.toBe(null); expect(parseInt(el3.getAttribute('gs-x'))).toBe(0); expect(parseInt(el3.getAttribute('gs-y'))).toBe(6); @@ -747,7 +747,7 @@ describe('gridstack', function() { expect(grid.engine.nodes.length).toEqual(0); expect(document.getElementById('item2')).toBe(null); - let el3 = grid.addWidget(widgetHTML); + let el3 = grid.makeWidget(widgetHTML); expect(el3).not.toBe(null); grid.removeWidget(el3, false); expect(grid.engine.nodes.length).toEqual(0); @@ -903,7 +903,7 @@ describe('gridstack', function() { }); it('should autoPosition (empty options)', function() { let grid = GridStack.init(); - let widget = grid.addWidget(); + let widget = grid.addWidget({ }); expect(parseInt(widget.getAttribute('gs-x'), 10)).toBe(8); expect(parseInt(widget.getAttribute('gs-y'), 10)).toBe(0); @@ -933,7 +933,7 @@ describe('gridstack', function() { it('null options should clear x position', function() { let grid = GridStack.init({float: true}); let HTML = '
'; - let widget = grid.addWidget(HTML, {x:null, y:null, w:undefined}); + let widget = grid.makeWidget(HTML, {x:null, y:null, w:undefined}); expect(parseInt(widget.getAttribute('gs-x'), 10)).toBe(8); expect(parseInt(widget.getAttribute('gs-y'), 10)).toBe(0); @@ -941,7 +941,7 @@ describe('gridstack', function() { it('width attr should be retained', function() { // #1276 let grid = GridStack.init({float: true}); let HTML = '
'; - let widget = grid.addWidget(HTML, {x: 1, y: 5}); + let widget = grid.makeWidget(HTML, {x: 1, y: 5}); expect(parseInt(widget.getAttribute('gs-x'), 10)).toBe(1); expect(parseInt(widget.getAttribute('gs-y'), 10)).toBe(5); expect(parseInt(widget.getAttribute('gs-w'), 10)).toBe(3); diff --git a/spec/utils-spec.ts b/spec/utils-spec.ts index f3590e815..27d324b5a 100644 --- a/spec/utils-spec.ts +++ b/spec/utils-spec.ts @@ -79,7 +79,7 @@ describe('gridstack utils', function() { expect(Utils.parseHeight('12.5cm')).toEqual(jasmine.objectContaining({h: 12.5, unit: 'cm'})); expect(Utils.parseHeight('12.5mm')).toEqual(jasmine.objectContaining({h: 12.5, unit: 'mm'})); expect(Utils.parseHeight('12.5')).toEqual(jasmine.objectContaining({h: 12.5, unit: 'px'})); - expect(function() { Utils.parseHeight('12.5 df'); }).toThrowError('Invalid height'); + expect(function() { Utils.parseHeight('12.5 df'); }).toThrowError('Invalid height val = 12.5 df'); }); it('should parse negative height value', function() { @@ -94,7 +94,7 @@ describe('gridstack utils', function() { expect(Utils.parseHeight('-12.3cm')).toEqual(jasmine.objectContaining({h: -12.3, unit: 'cm'})); expect(Utils.parseHeight('-12.3mm')).toEqual(jasmine.objectContaining({h: -12.3, unit: 'mm'})); expect(Utils.parseHeight('-12.5')).toEqual(jasmine.objectContaining({h: -12.5, unit: 'px'})); - expect(function() { Utils.parseHeight('-12.5 df'); }).toThrowError('Invalid height'); + expect(function() { Utils.parseHeight('-12.5 df'); }).toThrowError('Invalid height val = -12.5 df'); }); }); diff --git a/src/gridstack-engine.ts b/src/gridstack-engine.ts index 80917d6be..ba9bd8c7a 100644 --- a/src/gridstack-engine.ts +++ b/src/gridstack-engine.ts @@ -100,7 +100,11 @@ export class GridStackEngine { let didMove = false; const newOpt: GridStackMoveOpts = {nested: true, pack: false}; + let counter = 0; while (collide = collide || this.collide(node, area, opt.skip)) { // could collide with more than 1 item... so repeat for each + if (counter++ > this.nodes.length * 2) { + throw new Error("Infinite collide check"); + } let moved: boolean; // if colliding with a locked item OR loading (move after) OR moving down with top gravity (and collide could move up) -> skip past the collide, // but remember that skip down so we only do this once (and push others otherwise). diff --git a/tsconfig.json b/tsconfig.json index 5737f75f4..4b5c75da6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,9 +15,6 @@ "strict": false, "target": "ES2020" }, - "exclude": [ - "./src/**/*.spec.ts", - ], "include": [ "./src/**/*.ts" ],