import { defined } from "../../../Source/Cesium.js"; import { TimeInterval } from "../../../Source/Cesium.js"; import createViewer from "../../createViewer.js"; import DomEventSimulator from "../../DomEventSimulator.js"; import pollToPromise from "../../pollToPromise.js"; import { viewerDragDropMixin } from "../../../Source/Cesium.js"; describe( "Widgets/Viewer/viewerDragDropMixin", function () { var container; var viewer; beforeEach(function () { container = document.createElement("div"); container.id = "container"; container.style.display = "none"; document.body.appendChild(container); //Impersonate FileReader for drag and drop tests var fakeFileReader = jasmine.createSpyObj("FileReader", ["readAsText"]); fakeFileReader.readAsText = function (file) { if (defined(file.czmlString)) { this.onload({ target: { result: file.czmlString, }, }); } else { this.onerror({ target: { error: file.errorMessage, }, }); } }; spyOn(window, "FileReader").and.returnValue(fakeFileReader); }); afterEach(function () { if (viewer && !viewer.isDestroyed()) { viewer = viewer.destroy(); } document.body.removeChild(container); }); it("mixin sets default values", function () { viewer = createViewer(container); viewer.extend(viewerDragDropMixin); expect(viewer.dropTarget).toBe(viewer.container); expect(viewer.dropEnabled).toEqual(true); expect(viewer.clearOnDrop).toEqual(true); expect(viewer.clampToGround).toEqual(true); expect(viewer.flyToOnDrop).toEqual(true); }); it("clearOnDrop defaults to true when dataSourceBrowser is not used", function () { viewer = createViewer(container, { dataSourceBrowser: false, }); viewer.extend(viewerDragDropMixin); expect(viewer.clearOnDrop).toEqual(true); }); it("mixin sets option values", function () { viewer = createViewer(container); viewer.extend(viewerDragDropMixin, { dropTarget: document.body, clearOnDrop: false, clampToGround: false, flyToOnDrop: false, }); expect(viewer.dropTarget).toBe(document.body); expect(viewer.dropEnabled).toEqual(true); expect(viewer.clearOnDrop).toEqual(false); expect(viewer.clampToGround).toEqual(false); expect(viewer.flyToOnDrop).toEqual(false); }); it("mixin works with dropTarget id string", function () { viewer = createViewer(container); viewer.extend(viewerDragDropMixin, { dropTarget: "container", }); expect(viewer.dropTarget).toBe(container); }); var czml1 = [ { id: "document", version: "1.0", clock: { interval: "2000-01-01/2001-01-01", }, }, { id: "test", }, ]; var czml2 = [ { id: "document", version: "1.0", clock: { interval: "2000-01-02/2001-01-02", }, }, { id: "test2", }, ]; it("handleDrop processes drop event", function () { var mockEvent = { dataTransfer: { files: [ { name: "czml1.czml", czmlString: JSON.stringify(czml1), }, ], }, stopPropagation: function () {}, preventDefault: function () {}, }; viewer = createViewer(container); viewer.extend(viewerDragDropMixin); DomEventSimulator.fireMockEvent(viewer._handleDrop, mockEvent); return pollToPromise(function () { return viewer.dataSources.length === 1; }).then(function () { var dataSource = viewer.dataSources.get(0); var interval = TimeInterval.fromIso8601({ iso8601: czml1[0].clock.interval, }); expect(dataSource.entities.getById("test")).toBeDefined(); expect(dataSource.clock.startTime).toEqual(interval.start); expect(dataSource.clock.stopTime).toEqual(interval.stop); }); }); it("handleDrop processes drop event with multiple files", function () { var mockEvent = { dataTransfer: { files: [ { name: "czml1.czml", czmlString: JSON.stringify(czml1), }, { name: "czml2.czml", czmlString: JSON.stringify(czml2), }, ], }, stopPropagation: function () {}, preventDefault: function () {}, }; viewer = createViewer(container); viewer.extend(viewerDragDropMixin); DomEventSimulator.fireMockEvent(viewer._handleDrop, mockEvent); return pollToPromise(function () { return viewer.dataSources.length === 2; }).then(function () { var source1 = viewer.dataSources.get(0); var source2 = viewer.dataSources.get(1); expect(source1.entities.getById("test")).toBeDefined(); expect(source2.entities.getById("test2")).toBeDefined(); //Interval of first file should be used. var interval = TimeInterval.fromIso8601({ iso8601: czml1[0].clock.interval, }); expect(source1.clock.startTime).toEqual(interval.start); expect(source1.clock.stopTime).toEqual(interval.stop); }); }); it("handleDrop obeys clearOnDrop", function () { var mockEvent = { dataTransfer: { files: [ { name: "czml1.czml", czmlString: JSON.stringify(czml1), }, { name: "czml2.czml", czmlString: JSON.stringify(czml2), }, ], }, stopPropagation: function () {}, preventDefault: function () {}, }; viewer = createViewer(container); viewer.extend(viewerDragDropMixin); DomEventSimulator.fireMockEvent(viewer._handleDrop, mockEvent); return pollToPromise(function () { return viewer.dataSources.length === 2; }).then(function () { var source1 = viewer.dataSources.get(0); var source2 = viewer.dataSources.get(1); expect(source1.entities.getById("test")).toBeDefined(); expect(source2.entities.getById("test2")).toBeDefined(); //Interval of first file should be used. var interval = TimeInterval.fromIso8601({ iso8601: czml1[0].clock.interval, }); expect(source1.clock.startTime).toEqual(interval.start); expect(source1.clock.stopTime).toEqual(interval.stop); viewer.clearOnDrop = false; DomEventSimulator.fireMockEvent(viewer._handleDrop, mockEvent); return pollToPromise(function () { return viewer.dataSources.length === 4; }).then(function () { var source1 = viewer.dataSources.get(0); var source2 = viewer.dataSources.get(1); var source3 = viewer.dataSources.get(2); var source4 = viewer.dataSources.get(3); expect(source1.entities.getById("test")).toBeDefined(); expect(source2.entities.getById("test2")).toBeDefined(); expect(source3.entities.getById("test")).toBeDefined(); expect(source4.entities.getById("test2")).toBeDefined(); viewer.clearOnDrop = true; DomEventSimulator.fireMockEvent(viewer._handleDrop, mockEvent); return pollToPromise(function () { return viewer.dataSources.length === 2; }).then(function () { var source1 = viewer.dataSources.get(0); var source2 = viewer.dataSources.get(1); expect(source1.entities.getById("test")).toBeDefined(); expect(source2.entities.getById("test2")).toBeDefined(); //Interval of first file should be used. var interval = TimeInterval.fromIso8601({ iso8601: czml1[0].clock.interval, }); expect(source1.clock.startTime).toEqual(interval.start); expect(source1.clock.stopTime).toEqual(interval.stop); }); }); }); }); it("dropError is raised on exception", function () { var mockEvent = { dataTransfer: { files: [ { name: "czml1.czml", czmlString: "bad JSON", }, ], }, stopPropagation: function () {}, preventDefault: function () {}, }; viewer = createViewer(container); viewer.extend(viewerDragDropMixin); var spyListener = jasmine.createSpy("listener"); viewer.dropError.addEventListener(spyListener); DomEventSimulator.fireMockEvent(viewer._handleDrop, mockEvent); return pollToPromise(function () { return spyListener.calls.any(); }).then(function () { expect(spyListener).toHaveBeenCalledWith( viewer, "czml1.czml", jasmine.any(SyntaxError) ); viewer.dropError.removeEventListener(spyListener); }); }); it("dropError is raised FileReader error", function () { var mockEvent = { dataTransfer: { files: [ { name: "czml1.czml", errorMessage: "bad JSON", }, ], }, stopPropagation: function () {}, preventDefault: function () {}, }; viewer = createViewer(container); viewer.extend(viewerDragDropMixin); var spyListener = jasmine.createSpy("listener"); viewer.dropError.addEventListener(spyListener); DomEventSimulator.fireMockEvent(viewer._handleDrop, mockEvent); return pollToPromise(function () { return spyListener.calls.any(); }).then(function () { expect(spyListener).toHaveBeenCalledWith( viewer, mockEvent.dataTransfer.files[0].name, mockEvent.dataTransfer.files[0].errorMessage ); viewer.dropError.removeEventListener(spyListener); }); }); function MockContainer() { var events = {}; this.events = events; this.addEventListener = function (name, func, bubble) { events[name] = { func: func, bubble: bubble, }; }; this.removeEventListener = function (name, func, bubble) { var subscribed = events[name]; expect(subscribed.func).toBe(func); expect(subscribed.bubble).toEqual(bubble); delete events[name]; }; } it("enable/disable subscribes to provided dropTarget.", function () { var dropTarget = new MockContainer(); viewer = createViewer(container); viewer.extend(viewerDragDropMixin, { dropTarget: dropTarget, }); expect(dropTarget.events.drop).toBeDefined(); expect(dropTarget.events.dragenter).toBeDefined(); expect(dropTarget.events.dragover).toBeDefined(); expect(dropTarget.events.dragexit).toBeDefined(); viewer.dropEnabled = false; expect(dropTarget.events.drop).toBeUndefined(); expect(dropTarget.events.dragenter).toBeUndefined(); expect(dropTarget.events.dragover).toBeUndefined(); expect(dropTarget.events.dragexit).toBeUndefined(); viewer.dropEnabled = true; expect(dropTarget.events.drop).toBeDefined(); expect(dropTarget.events.dragenter).toBeDefined(); expect(dropTarget.events.dragover).toBeDefined(); expect(dropTarget.events.dragexit).toBeDefined(); }); it("can set new dropTarget.", function () { var dropTarget1 = new MockContainer(); var dropTarget2 = new MockContainer(); viewer = createViewer(container); viewer.extend(viewerDragDropMixin, { dropTarget: dropTarget1, }); expect(dropTarget1.events.drop).toBeDefined(); expect(dropTarget1.events.dragenter).toBeDefined(); expect(dropTarget1.events.dragover).toBeDefined(); expect(dropTarget1.events.dragexit).toBeDefined(); viewer.dropTarget = dropTarget2; expect(dropTarget1.events.drop).toBeUndefined(); expect(dropTarget1.events.dragenter).toBeUndefined(); expect(dropTarget1.events.dragover).toBeUndefined(); expect(dropTarget1.events.dragexit).toBeUndefined(); expect(dropTarget2.events.drop).toBeDefined(); expect(dropTarget2.events.dragenter).toBeDefined(); expect(dropTarget2.events.dragover).toBeDefined(); expect(dropTarget2.events.dragexit).toBeDefined(); }); it("can set proxy.", function () { var proxy = {}; viewer = createViewer(container); viewer.extend(viewerDragDropMixin, { proxy: proxy, }); expect(viewer.proxy).toBe(proxy); }); it("throws with undefined viewer", function () { expect(function () { viewerDragDropMixin(undefined); }).toThrowDeveloperError(); }); it("throws with non-existant string container", function () { viewer = createViewer(container); expect(function () { viewer.extend(viewerDragDropMixin, { dropTarget: "doesNotExist", }); }).toThrowDeveloperError(); }); it("throws if dropTarget property already added by another mixin.", function () { viewer = createViewer(container); viewer.dropTarget = true; expect(function () { viewer.extend(viewerDragDropMixin); }).toThrowDeveloperError(); }); it("throws if dropEnabled property already added by another mixin.", function () { viewer = createViewer(container); viewer.dropEnabled = true; expect(function () { viewer.extend(viewerDragDropMixin); }).toThrowDeveloperError(); }); it("throws if dropError property already added by another mixin.", function () { viewer = createViewer(container); viewer.dropError = true; expect(function () { viewer.extend(viewerDragDropMixin); }).toThrowDeveloperError(); }); it("throws if clearOnDrop property already added by another mixin.", function () { viewer = createViewer(container); viewer.clearOnDrop = true; expect(function () { viewer.extend(viewerDragDropMixin); }).toThrowDeveloperError(); }); it("throws if flyToOnDrop property already added by another mixin.", function () { viewer = createViewer(container); viewer.flyToOnDrop = true; expect(function () { viewer.extend(viewerDragDropMixin); }).toThrowDeveloperError(); }); it("setting dropTarget to undefined throws exception", function () { viewer = createViewer(container); viewer.extend(viewerDragDropMixin); expect(function () { viewer.dropTarget = undefined; }).toThrowDeveloperError(); }); }, "WebGL" );