UNPKG

extjs-gpl

Version:

GPL licensed version of Sencha Ext JS

903 lines (785 loc) 29.7 kB
// This will test all interaction between drag/drop targets. describe("Ext.drag.Manager", function() { var helper = Ext.testHelper, touchId = 0, cursorTrack, source, target, dragEl, dropEl; function makeEl(cfg) { return Ext.getBody().createChild(cfg); } function makeDragEl(x, y) { if (typeof x !== 'number') { x = 5; } if (typeof y !== 'number') { y = 5; } dragEl = makeEl({ style: { position: 'absolute', width: '20px', height: '20px', left: x + 'px', top: y + 'px', border: '1px solid red' } }); } function makeDropEl(x, y) { if (typeof x !== 'number') { x = 50; } if (typeof y !== 'number') { y = 50; } dropEl = makeEl({ style: { position: 'absolute', width: '100px', height: '100px', left: x + 'px', top: y + 'px', border: '1px solid blue' } }); } function makeSource(cfg) { cfg = cfg || {}; if (!cfg.element) { if (!dragEl) { makeDragEl(); } cfg.element = dragEl; } source = new Ext.drag.Source(cfg); } function makeTarget(cfg) { cfg = cfg || {}; if (!cfg.element) { if (!dropEl) { makeDropEl(); } cfg.element = dropEl; } target = new Ext.drag.Target(cfg); } function start(cfg, target) { cursorTrack = [cfg.x || 0, cfg.y || 0]; helper.touchStart(target || dragEl, cfg); } function move(cfg, target) { cursorTrack = [cfg.x || 0, cfg.y || 0]; helper.touchMove(target || dragEl, cfg); } function end(cfg, target) { cursorTrack = [cfg.x || 0, cfg.y || 0]; helper.touchEnd(target || dragEl, cfg); } function cancel(cfg, target) { cursorTrack = [cfg.x || 0, cfg.y || 0]; helper.touchCancel(target || dragEl, cfg); } function startDrag(x, y, target) { runs(function() { var xy = source.getElement().getXY(); x = x || xy[0]; y = y || xy[1]; start({ id: touchId, x: x, y: y }, target); }); waitsForAnimation(); } function startPosDrag(xPos, yPos, target) { runs(function() { var el = source.getElement(), xy = source.getElement().getXY(), size = el.getSize(), xOffset = 0, yOffset = 0; if (xPos === 'middle') { xOffset = size.width / 2; } else if (xPos === 'end') { xOffset = size.width; } if (yPos === 'middle') { yOffset = size.height / 2; } else if (yPos === 'end') { yOffset = size.height; } start({ id: touchId, x: xy[0] + xOffset, y: xy[1] + yOffset }, target); }); waitsForAnimation(); } function moveBy(x, y, target) { runs(function() { move({ id: touchId, x: cursorTrack[0] + (x || 0), y: cursorTrack[1] + (y || 0) }, target); }); waitsForAnimation(); } function endDrag(x, y, target) { runs(function() { x = x || cursorTrack[0]; y = y || cursorTrack[1]; end({ id: touchId, x: x, y: y }, target); }); waitsForAnimation(); runs(function() { ++touchId; }); } function runsExpectCallCount(spies, n) { runs(function() { if (!Ext.isArray(spies)) { spies = [spies]; } Ext.Array.forEach(spies, function(spy) { expect(spy.callCount).toBe(n); }); }); } beforeEach(function() { cursorTrack = null; ++touchId; }); afterEach(function() { cursorTrack = source = target = dragEl = dropEl = Ext.destroy(dragEl, dropEl, source, target); }); describe("target matching", function() { var enterSpy, leaveSpy; beforeEach(function() { enterSpy = jasmine.createSpy(); leaveSpy = jasmine.createSpy(); }); afterEach(function() { leaveSpy = enterSpy = null; }); function setup() { makeSource(); makeTarget(); target.on('dragenter', enterSpy); target.on('dragleave', leaveSpy); } describe("simple matching", function() { it("should match an enter from the top", function() { makeDragEl(70, 10); makeDropEl(50, 50); setup(); startPosDrag('middle', 'end'); moveBy(0, 19); runsExpectCallCount(enterSpy, 0); moveBy(0, 2); runsExpectCallCount(enterSpy, 1); moveBy(0, 10); runsExpectCallCount(enterSpy, 1); moveBy(0, -10); runsExpectCallCount(enterSpy, 1); runsExpectCallCount(leaveSpy, 0); moveBy(0, -2); runsExpectCallCount(leaveSpy, 1); endDrag(); }); it("should match an enter from the top right", function() { makeDragEl(170, 10); makeDropEl(50, 50); setup(); startPosDrag('start', 'end'); moveBy(-19, 19); runsExpectCallCount(enterSpy, 0); moveBy(-2, 2); runsExpectCallCount(enterSpy, 1); moveBy(-10, 10); runsExpectCallCount(enterSpy, 1); moveBy(10, -10); runsExpectCallCount(enterSpy, 1); runsExpectCallCount(leaveSpy, 0); moveBy(2, -2); runsExpectCallCount(leaveSpy, 1); endDrag(); }); it("should match an enter from the right", function() { makeDragEl(170, 80); makeDropEl(50, 50); setup(); startPosDrag('start', 'middle'); moveBy(-19, 0); runsExpectCallCount(enterSpy, 0); moveBy(-2, 0); runsExpectCallCount(enterSpy, 1); moveBy(-10, 0); runsExpectCallCount(enterSpy, 1); moveBy(10, 0); runsExpectCallCount(enterSpy, 1); runsExpectCallCount(leaveSpy, 0); moveBy(2, 0); runsExpectCallCount(leaveSpy, 1); endDrag(); }); it("should match an enter from the bottom right", function() { makeDragEl(170, 170); makeDropEl(50, 50); setup(); startPosDrag('start', 'start'); moveBy(-19, -19); runsExpectCallCount(enterSpy, 0); moveBy(-2, -2); runsExpectCallCount(enterSpy, 1); moveBy(-10, -10); runsExpectCallCount(enterSpy, 1); moveBy(10, 10); runsExpectCallCount(enterSpy, 1); runsExpectCallCount(leaveSpy, 0); moveBy(2, 2); runsExpectCallCount(leaveSpy, 1); endDrag(); }); it("should match an enter from the bottom", function() { makeDragEl(70, 170); makeDropEl(50, 50); setup(); startPosDrag('middle', 'start'); moveBy(0, -19); runsExpectCallCount(enterSpy, 0); moveBy(0, -2); runsExpectCallCount(enterSpy, 1); moveBy(0, -10); runsExpectCallCount(enterSpy, 1); moveBy(0, 10); runsExpectCallCount(enterSpy, 1); runsExpectCallCount(leaveSpy, 0); moveBy(0, 2); runsExpectCallCount(leaveSpy, 1); endDrag(); }); it("should match an enter from the bottom left", function() { makeDragEl(10, 170); makeDropEl(50, 50); setup(); startPosDrag('end', 'start'); moveBy(19, -19); runsExpectCallCount(enterSpy, 0); moveBy(2, -2); runsExpectCallCount(enterSpy, 1); moveBy(10, -10); runsExpectCallCount(enterSpy, 1); moveBy(-10, 10); runsExpectCallCount(enterSpy, 1); runsExpectCallCount(leaveSpy, 0); moveBy(-2, 2); runsExpectCallCount(leaveSpy, 1); endDrag(); }); it("should match an enter from the left", function() { makeDragEl(10, 80); makeDropEl(50, 50); setup(); startPosDrag('end', 'middle'); moveBy(19, 0); runsExpectCallCount(enterSpy, 0); moveBy(2, 0); runsExpectCallCount(enterSpy, 1); moveBy(10, 0); runsExpectCallCount(enterSpy, 1); moveBy(-10, 0); runsExpectCallCount(enterSpy, 1); runsExpectCallCount(leaveSpy, 0); moveBy(-2, 0); runsExpectCallCount(leaveSpy, 1); endDrag(); }); it("should match an enter from the top left", function() { makeDragEl(10, 10); makeDropEl(50, 50); setup(); startPosDrag('end', 'end'); moveBy(19, 19); runsExpectCallCount(enterSpy, 0); moveBy(2, 2); runsExpectCallCount(enterSpy, 1); moveBy(10, 10); runsExpectCallCount(enterSpy, 1); moveBy(-10, -10); runsExpectCallCount(enterSpy, 1); runsExpectCallCount(leaveSpy, 0); moveBy(-2, -2); runsExpectCallCount(leaveSpy, 1); endDrag(); }); }); describe("z-index", function() { function makeZIndexDrop(zIndex, color) { var el = makeEl({ style: { position: 'absolute', width: '100px', height: '100px', left: '50px', top: '50px', zIndex: zIndex, backgroundColor: color } }); return new Ext.drag.Target({ element: el }); } it("should only match the topmost z-index", function() { var drop1 = makeZIndexDrop(300, 'red'), drop2 = makeZIndexDrop(200, 'blue'), drop3 = makeZIndexDrop(100, 'green'); makeDragEl(); makeSource(); drop1.on('dragenter', enterSpy.andCallFake(function(source, info) { enterSpy.mostRecentCall.dragInfo = info.clone(); })); drop1.on('dragleave', leaveSpy.andCallFake(function(source, info) { leaveSpy.mostRecentCall.dragInfo = info.clone(); })); startDrag(); moveBy(50, 50); runs(function() { expect(enterSpy.callCount).toBe(1); expect(enterSpy.mostRecentCall.dragInfo.target).toBe(drop1); }); moveBy(200, 200); runs(function() { expect(leaveSpy.callCount).toBe(1); expect(leaveSpy.mostRecentCall.dragInfo.target).toBe(drop1); }); endDrag(); runs(function() { Ext.destroy(drop1, drop2, drop3); }); }); it("should not move to a lower z-index if the topmost doesn't accept the drop", function() { var drop1 = makeZIndexDrop(300, 'red'), drop2 = makeZIndexDrop(200, 'blue'), drop3 = makeZIndexDrop(100, 'green'); makeDragEl(); makeSource(); drop1.disable(); drop2.on('dragenter', enterSpy); drop3.on('dragenter', enterSpy); startDrag(); moveBy(50, 50); runsExpectCallCount(enterSpy, 0); endDrag(); runs(function() { Ext.destroy(drop1, drop2, drop3); }); }); }); describe("nested targets", function() { it("should transition to the inner target", function() { makeDragEl(); makeDropEl(); var inner = new Ext.drag.Target({ element: Ext.getBody().createChild({ style: { position: 'absolute', width: '50px', height: '50px', left: '70px', top: '70px', border: '1px solid green' } }) }); makeSource(); makeTarget(); target.on('dragenter', enterSpy.andCallFake(function(target, info) { enterSpy.mostRecentCall.dragInfo = info.clone(); })); target.on('dragleave', leaveSpy.andCallFake(function(target, info) { leaveSpy.mostRecentCall.dragInfo = info.clone(); })); inner.on('dragenter', enterSpy.andCallFake(function(target, info) { enterSpy.mostRecentCall.dragInfo = info.clone(); })); inner.on('dragleave', leaveSpy.andCallFake(function(target, info) { leaveSpy.mostRecentCall.dragInfo = info.clone(); })); startDrag(); moveBy(50, 50); runs(function() { expect(enterSpy.callCount).toBe(1); expect(enterSpy.mostRecentCall.dragInfo.target).toBe(target); }); moveBy(30, 30); runs(function() { expect(leaveSpy.callCount).toBe(1); expect(leaveSpy.mostRecentCall.dragInfo.target).toBe(target); expect(enterSpy.callCount).toBe(2); expect(enterSpy.mostRecentCall.dragInfo.target).toBe(inner); }); moveBy(40, 40); runs(function() { expect(leaveSpy.callCount).toBe(2); expect(leaveSpy.mostRecentCall.dragInfo.target).toBe(inner); expect(enterSpy.callCount).toBe(3); expect(enterSpy.mostRecentCall.dragInfo.target).toBe(target); }); moveBy(100, 100); runs(function() { expect(leaveSpy.callCount).toBe(3); expect(leaveSpy.mostRecentCall.dragInfo.target).toBe(target); expect(enterSpy.callCount).toBe(3); }); runs(function() { inner.destroy(); }); }); }); describe("scroll", function() { it("should match targets when the document is scrolled", function() { var Scroller = Ext.scroll.Scroller, stretcher; makeDragEl(405, 405); makeDropEl(450, 450); setup(); if (Scroller && Scroller.viewport) { stretcher = Ext.getBody().createChild({ style: { width: '5000px', height: '5000px', border: '1px solid red' } }); Scroller.viewport.scrollTo(0, 400); startDrag(); moveBy(50, 50); runsExpectCallCount(enterSpy, 1); moveBy(-20, -20); runsExpectCallCount(leaveSpy, 1); endDrag(); runs(function() { stretcher.remove(); }); } }); }); }); describe("restrictions", function() { var enterSpy, leaveSpy; beforeEach(function() { makeDragEl(); makeDropEl(); enterSpy = jasmine.createSpy(); leaveSpy = jasmine.createSpy(); }); afterEach(function() { enterSpy = leaveSpy = null; }); function dragInOutTarget() { target.on('dragenter', enterSpy.andCallFake(function(target, info) { enterSpy.mostRecentCall.valid = info.valid; })); target.on('dragleave', leaveSpy.andCallFake(function(target, info) { leaveSpy.mostRecentCall.valid = info.valid; })); startDrag(); moveBy(50, 50); moveBy(200, 200); endDrag(); } function runsExpectValid(spies, valid) { runs(function() { if (!Ext.isArray(spies)) { spies = [spies]; } Ext.Array.forEach(spies, function(spy) { expect(spy.mostRecentCall.valid).toBe(valid); }); }); } describe("disabled", function() { it("should not interact if the target is disabled", function() { makeSource(); makeTarget(); target.disable(); dragInOutTarget(); runsExpectValid([enterSpy, leaveSpy], false); }); }); describe("accepts", function() { it("should accept by default", function() { makeSource(); makeTarget(); dragInOutTarget(); runsExpectValid([enterSpy, leaveSpy], true); }); it("should not call accept if target is disabled", function() { var accepts = jasmine.createSpy().andReturn(true); makeSource(); makeTarget({ accepts: accepts }); target.disable(); dragInOutTarget(); runsExpectCallCount(accepts, 0); }); it("should not call accept if groups don't match", function() { var accepts = jasmine.createSpy().andReturn(true); makeSource({ groups: 'foo' }); makeTarget({ groups: 'bar', accepts: accepts }); dragInOutTarget(); runsExpectCallCount(accepts, 0); }); it("should not enter the target if it doesn't accept the data", function() { var accepts = jasmine.createSpy().andReturn(false); makeSource(); makeTarget({ accepts: accepts }); dragInOutTarget(); runsExpectValid([enterSpy, leaveSpy], false); }); it("should pass the info object", function() { var accepts = jasmine.createSpy().andReturn(true); makeSource(); makeTarget({ accepts: accepts }); startDrag(); moveBy(50, 50); runs(function() { expect(accepts.mostRecentCall.args[0] instanceof Ext.drag.Info).toBe(true); }); endDrag(); }); it("should only call accepts once it enters the target", function() { var accepts = jasmine.createSpy().andReturn(true); makeSource(); makeTarget({ accepts: accepts }); startDrag(); moveBy(10, 10); runsExpectCallCount(accepts, 0); moveBy(10, 10); runsExpectCallCount(accepts, 0); moveBy(30, 30); runsExpectCallCount(accepts, 1); endDrag(); }); it("should only call accepts once when it enters the target and the source is accepted", function() { var accepts = jasmine.createSpy().andReturn(true); makeSource(); makeTarget({ accepts: accepts }); startDrag(); moveBy(50, 50); runsExpectCallCount(accepts, 1); // Still inside the target moveBy(5, 5); runsExpectCallCount(accepts, 1); moveBy(5, 5); runsExpectCallCount(accepts, 1); moveBy(5, 5); runsExpectCallCount(accepts, 1); // Outside the target moveBy(200, 200); runsExpectCallCount(accepts, 1); endDrag(); }); it("should only call accepts once when it enters the target and the source is not accepted", function() { var accepts = jasmine.createSpy().andReturn(false); makeSource(); makeTarget({ accepts: accepts }); startDrag(); moveBy(50, 50); runsExpectCallCount(accepts, 1); // Still inside the target moveBy(5, 5); runsExpectCallCount(accepts, 1); moveBy(5, 5); runsExpectCallCount(accepts, 1); moveBy(5, 5); runsExpectCallCount(accepts, 1); // Outside the target moveBy(200, 200); runsExpectCallCount(accepts, 1); endDrag(); }); it("should call accepts each time it enters the target", function() { var accepts = jasmine.createSpy().andReturn(true); makeSource(); makeTarget({ accepts: accepts }); startDrag(); moveBy(50, 50); runsExpectCallCount(accepts, 1); moveBy(-50, -50); runsExpectCallCount(accepts, 1); moveBy(50, 50); runsExpectCallCount(accepts, 2); moveBy(-50, -50); runsExpectCallCount(accepts, 2); moveBy(50, 50); runsExpectCallCount(accepts, 3); endDrag(); }); }); describe("groups", function() { describe("source: no group, target: no group", function() { it("should interact", function() { makeSource(); makeTarget(); dragInOutTarget(); runsExpectValid([enterSpy, leaveSpy], true); }); }); describe("source: no group, target: one group", function() { it("should not interact", function() { makeSource(); makeTarget({ groups: 'a' }); dragInOutTarget(); runsExpectValid([enterSpy, leaveSpy], false); }); }); describe("source: no group, target: multiple groups", function() { it("should not interact", function() { makeSource(); makeTarget({ groups: ['a', 'b', 'c'] }); dragInOutTarget(); runsExpectValid([enterSpy, leaveSpy], false); }); }); describe("source: one group, target: no group", function() { it("should not interact", function() { makeSource({ groups: 'a' }); makeTarget(); dragInOutTarget(); runsExpectValid([enterSpy, leaveSpy], false); }); }); describe("source: one group, target: one group", function() { it("should interact if the groups are the same", function() { makeSource({ groups: 'a' }); makeTarget({ groups: 'a' }); dragInOutTarget(); runsExpectValid([enterSpy, leaveSpy], true); }); it("should not interact if the groups are different", function() { makeSource({ groups: 'a' }); makeTarget({ groups: 'b' }); dragInOutTarget(); runsExpectValid([enterSpy, leaveSpy], false); }); }); describe("source: one group, target: multiple groups", function() { it("should interact if the source group exists in the target groups", function() { makeSource({ groups: 'b' }); makeTarget({ groups: ['a', 'b', 'c'] }); dragInOutTarget(); runsExpectValid([enterSpy, leaveSpy], true); }); it("should not interact if the source group doesn't exist in the target groups", function() { makeSource({ groups: 'bleh' }); makeTarget({ groups: ['a', 'b', 'c'] }); dragInOutTarget(); runsExpectValid([enterSpy, leaveSpy], false); }); }); describe("source: multiple groups, target: no group", function() { it("should not interact", function() { makeSource({ groups: ['a', 'b', 'c'] }); makeTarget(); dragInOutTarget(); runsExpectValid([enterSpy, leaveSpy], false); }); }); describe("source: multiple groups, target: one group", function() { it("should interact if the target group exists in the source groups", function() { makeSource({ groups: ['a', 'b', 'c'] }); makeTarget({ groups: 'b' }); dragInOutTarget(); runsExpectValid([enterSpy, leaveSpy], true); }); it("should not interact if the target group doesn't exist in the source groups", function() { makeSource({ groups: ['a', 'b', 'c'] }); makeTarget({ groups: 'bleh' }); dragInOutTarget(); runsExpectValid([enterSpy, leaveSpy], false); }); }); describe("source: multiple groups, target: multiple groups", function() { it("should interact if the groups intersect", function() { makeSource({ groups: ['a', 'b', 'c'] }); makeTarget({ groups: ['a', 'c'] }); dragInOutTarget(); runsExpectValid([enterSpy, leaveSpy], true); }); it("should not interact if the groups don't intersect", function() { makeSource({ groups: ['a', 'b', 'c'] }); makeTarget({ groups: ['x', 'y', 'z'] }); dragInOutTarget(); runsExpectValid([enterSpy, leaveSpy], false); }); }); }); }); });