diff --git a/spec/pane-container-spec.coffee b/spec/pane-container-spec.coffee index 42dad2fa9..1442f24e4 100644 --- a/spec/pane-container-spec.coffee +++ b/spec/pane-container-spec.coffee @@ -2,6 +2,16 @@ PaneContainer = require '../src/pane-container' Pane = require '../src/pane' describe "PaneContainer", -> + [confirm, params] = [] + + beforeEach -> + confirm = jasmine.createSpy('confirm').andReturn(0) + params = { + config: atom.config, + confirm: confirm, + deserializerManager: atom.deserializers + } + describe "serialization", -> [containerA, pane1A, pane2A, pane3A] = [] @@ -12,7 +22,7 @@ describe "PaneContainer", -> @deserialize: -> new this serialize: -> deserializer: 'Item' - containerA = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + containerA = new PaneContainer(params) pane1A = containerA.getActivePane() pane1A.addItem(new Item) pane2A = pane1A.splitRight(items: [new Item]) @@ -22,7 +32,7 @@ describe "PaneContainer", -> it "preserves the focused pane across serialization", -> expect(pane3A.focused).toBe true - containerB = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + containerB = new PaneContainer(params) containerB.deserialize(containerA.serialize(), atom.deserializers) [pane1B, pane2B, pane3B] = containerB.getPanes() expect(pane3B.focused).toBe true @@ -31,7 +41,7 @@ describe "PaneContainer", -> pane3A.activate() expect(containerA.getActivePane()).toBe pane3A - containerB = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + containerB = new PaneContainer(params) containerB.deserialize(containerA.serialize(), atom.deserializers) [pane1B, pane2B, pane3B] = containerB.getPanes() expect(containerB.getActivePane()).toBe pane3B @@ -40,7 +50,7 @@ describe "PaneContainer", -> pane3A.activate() state = containerA.serialize() state.activePaneId = -22 - containerB = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + containerB = new PaneContainer(params) containerB.deserialize(state, atom.deserializers) expect(containerB.getActivePane()).toBe containerB.getPanes()[0] @@ -51,7 +61,7 @@ describe "PaneContainer", -> describe "if the 'core.destroyEmptyPanes' config option is false (the default)", -> it "leaves the empty panes intact", -> state = containerA.serialize() - containerB = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + containerB = new PaneContainer(params) containerB.deserialize(state, atom.deserializers) [leftPane, column] = containerB.getRoot().getChildren() [topPane, bottomPane] = column.getChildren() @@ -65,7 +75,7 @@ describe "PaneContainer", -> atom.config.set('core.destroyEmptyPanes', true) state = containerA.serialize() - containerB = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + containerB = new PaneContainer(params) containerB.deserialize(state, atom.deserializers) [leftPane, rightPane] = containerB.getRoot().getChildren() @@ -73,7 +83,7 @@ describe "PaneContainer", -> expect(rightPane.getItems().length).toBe 1 it "does not allow the root pane to be destroyed", -> - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(params) container.getRoot().destroy() expect(container.getRoot()).toBeDefined() expect(container.getRoot().isDestroyed()).toBe false @@ -82,7 +92,7 @@ describe "PaneContainer", -> [container, pane1, pane2] = [] beforeEach -> - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(params) pane1 = container.getRoot() it "returns the first pane if no pane has been made active", -> @@ -111,7 +121,7 @@ describe "PaneContainer", -> [container, pane1, pane2, observed] = [] beforeEach -> - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(params) container.getRoot().addItems([new Object, new Object]) container.getRoot().splitRight(items: [new Object, new Object]) [pane1, pane2] = container.getPanes() @@ -131,7 +141,7 @@ describe "PaneContainer", -> describe "::observePanes()", -> it "invokes observers with all current and future panes", -> - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(params) container.getRoot().splitRight() [pane1, pane2] = container.getPanes() @@ -145,7 +155,7 @@ describe "PaneContainer", -> describe "::observePaneItems()", -> it "invokes observers with all current and future pane items", -> - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(params) container.getRoot().addItems([new Object, new Object]) container.getRoot().splitRight(items: [new Object]) [pane1, pane2] = container.getPanes() @@ -165,27 +175,27 @@ describe "PaneContainer", -> shouldPromptToSave: -> true getURI: -> 'test' - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(params) container.getRoot().splitRight() [pane1, pane2] = container.getPanes() pane1.addItem(new TestItem) pane2.addItem(new TestItem) it "returns true if the user saves all modified files when prompted", -> - spyOn(atom, "confirm").andReturn(0) + confirm.andReturn(0) saved = container.confirmClose() expect(saved).toBeTruthy() - expect(atom.confirm).toHaveBeenCalled() + expect(confirm).toHaveBeenCalled() it "returns false if the user cancels saving any modified file", -> - spyOn(atom, "confirm").andReturn(1) + confirm.andReturn(1) saved = container.confirmClose() expect(saved).toBeFalsy() - expect(atom.confirm).toHaveBeenCalled() + expect(confirm).toHaveBeenCalled() describe "::onDidAddPane(callback)", -> it "invokes the given callback when panes are added", -> - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(params) events = [] container.onDidAddPane (event) -> events.push(event) @@ -202,7 +212,7 @@ describe "PaneContainer", -> destroy: -> @_isDestroyed = true isDestroyed: -> @_isDestroyed - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(params) events = [] container.onWillDestroyPane (event) -> itemsDestroyed = (item.isDestroyed() for item in event.pane.getItems()) @@ -218,7 +228,7 @@ describe "PaneContainer", -> describe "::onDidDestroyPane(callback)", -> it "invokes the given callback when panes are destroyed", -> - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(params) events = [] container.onDidDestroyPane (event) -> events.push(event) @@ -233,7 +243,7 @@ describe "PaneContainer", -> describe "::onWillDestroyPaneItem() and ::onDidDestroyPaneItem", -> it "invokes the given callbacks when an item will be destroyed on any pane", -> - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(params) pane1 = container.getRoot() item1 = new Object item2 = new Object @@ -260,7 +270,7 @@ describe "PaneContainer", -> describe "::saveAll()", -> it "saves all open pane items", -> - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(params) pane1 = container.getRoot() pane2 = pane1.splitRight() diff --git a/spec/pane-spec.coffee b/spec/pane-spec.coffee index 4186e33a1..ca277f9af 100644 --- a/spec/pane-spec.coffee +++ b/spec/pane-spec.coffee @@ -1,10 +1,11 @@ +{extend} = require 'underscore-plus' {Emitter} = require 'event-kit' Pane = require '../src/pane' PaneAxis = require '../src/pane-axis' PaneContainer = require '../src/pane-container' describe "Pane", -> - deserializerDisposable = null + [confirm, deserializerDisposable] = [] class Item @deserialize: ({name, uri}) -> new this(name, uri) @@ -19,18 +20,27 @@ describe "Pane", -> isDestroyed: -> @destroyed beforeEach -> + confirm = jasmine.createSpy('confirm') deserializerDisposable = atom.deserializers.add(Item) afterEach -> deserializerDisposable.dispose() + paneParams = (params) -> + extend({ + confirm: confirm, + config: atom.config, + deserializerManager: atom.deserializers, + notificationManager: atom.notifications + }, params) + describe "construction", -> it "sets the active item to the first item", -> - pane = new Pane(items: [new Item("A"), new Item("B")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B")])) expect(pane.getActiveItem()).toBe pane.itemAtIndex(0) it "compacts the items array", -> - pane = new Pane(items: [undefined, new Item("A"), null, new Item("B")]) + pane = new Pane(paneParams(items: [undefined, new Item("A"), null, new Item("B")])) expect(pane.getItems().length).toBe 2 expect(pane.getActiveItem()).toBe pane.itemAtIndex(0) @@ -38,7 +48,7 @@ describe "Pane", -> [container, pane1, pane2] = [] beforeEach -> - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(config: atom.config, confirm: confirm) container.getActivePane().splitRight() [pane1, pane2] = container.getPanes() @@ -76,14 +86,14 @@ describe "Pane", -> describe "::addItem(item, index)", -> it "adds the item at the given index", -> - pane = new Pane(items: [new Item("A"), new Item("B")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B")])) [item1, item2] = pane.getItems() item3 = new Item("C") pane.addItem(item3, 1) expect(pane.getItems()).toEqual [item1, item3, item2] it "adds the item after the active item if no index is provided", -> - pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C")])) [item1, item2, item3] = pane.getItems() pane.activateItem(item2) item4 = new Item("D") @@ -91,13 +101,13 @@ describe "Pane", -> expect(pane.getItems()).toEqual [item1, item2, item4, item3] it "sets the active item after adding the first item", -> - pane = new Pane + pane = new Pane(paneParams()) item = new Item("A") pane.addItem(item) expect(pane.getActiveItem()).toBe item it "invokes ::onDidAddItem() observers", -> - pane = new Pane(items: [new Item("A"), new Item("B")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B")])) events = [] pane.onDidAddItem (event) -> events.push(event) @@ -107,14 +117,14 @@ describe "Pane", -> it "throws an exception if the item is already present on a pane", -> item = new Item("A") - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(config: atom.config, confirm: confirm) pane1 = container.getActivePane() pane1.addItem(item) pane2 = pane1.splitRight() expect(-> pane2.addItem(item)).toThrow() it "throws an exception if the item isn't an object", -> - pane = new Pane(items: []) + pane = new Pane(paneParams(items: [])) expect(-> pane.addItem(null)).toThrow() expect(-> pane.addItem('foo')).toThrow() expect(-> pane.addItem(1)).toThrow() @@ -123,7 +133,7 @@ describe "Pane", -> pane = null beforeEach -> - pane = new Pane(items: [new Item("A"), new Item("B")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B")])) it "changes the active item to the current item", -> expect(pane.getActiveItem()).toBe pane.itemAtIndex(0) @@ -144,7 +154,7 @@ describe "Pane", -> describe "::activateNextItem() and ::activatePreviousItem()", -> it "sets the active item to the next/previous item, looping around at either end", -> - pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C")])) [item1, item2, item3] = pane.getItems() expect(pane.getActiveItem()).toBe item1 @@ -159,7 +169,7 @@ describe "Pane", -> describe "::moveItemRight() and ::moveItemLeft()", -> it "moves the active item to the right and left, without looping around at either end", -> - pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C")])) [item1, item2, item3] = pane.getItems() pane.activateItemAtIndex(0) @@ -177,7 +187,7 @@ describe "Pane", -> describe "::activateItemAtIndex(index)", -> it "activates the item at the given index", -> - pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C")])) [item1, item2, item3] = pane.getItems() pane.activateItemAtIndex(2) expect(pane.getActiveItem()).toBe item3 @@ -196,7 +206,7 @@ describe "Pane", -> [pane, item1, item2, item3] = [] beforeEach -> - pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C")])) [item1, item2, item3] = pane.getItems() it "removes the item from the items list and destroyes it", -> @@ -260,7 +270,7 @@ describe "Pane", -> describe "when the item has a uri", -> it "saves the item before destroying it", -> itemURI = "test" - spyOn(atom, 'confirm').andReturn(0) + confirm.andReturn(0) pane.destroyItem(item1) expect(item1.save).toHaveBeenCalled() @@ -272,7 +282,7 @@ describe "Pane", -> itemURI = null spyOn(atom, 'showSaveDialogSync').andReturn("/selected/path") - spyOn(atom, 'confirm').andReturn(0) + confirm.andReturn(0) pane.destroyItem(item1) expect(atom.showSaveDialogSync).toHaveBeenCalled() @@ -282,7 +292,7 @@ describe "Pane", -> describe "if the [Don't Save] option is selected", -> it "removes and destroys the item without saving it", -> - spyOn(atom, 'confirm').andReturn(2) + confirm.andReturn(2) pane.destroyItem(item1) expect(item1.save).not.toHaveBeenCalled() @@ -291,7 +301,7 @@ describe "Pane", -> describe "if the [Cancel] option is selected", -> it "does not save, remove, or destroy the item", -> - spyOn(atom, 'confirm').andReturn(1) + confirm.andReturn(1) pane.destroyItem(item1) expect(item1.save).not.toHaveBeenCalled() @@ -316,19 +326,19 @@ describe "Pane", -> describe "::destroyActiveItem()", -> it "destroys the active item", -> - pane = new Pane(items: [new Item("A"), new Item("B")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B")])) activeItem = pane.getActiveItem() pane.destroyActiveItem() expect(activeItem.isDestroyed()).toBe true expect(activeItem in pane.getItems()).toBe false it "does not throw an exception if there are no more items", -> - pane = new Pane + pane = new Pane(paneParams()) pane.destroyActiveItem() describe "::destroyItems()", -> it "destroys all items", -> - pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C")])) [item1, item2, item3] = pane.getItems() pane.destroyItems() expect(item1.isDestroyed()).toBe true @@ -338,7 +348,7 @@ describe "Pane", -> describe "::observeItems()", -> it "invokes the observer with all current and future items", -> - pane = new Pane(items: [new Item, new Item]) + pane = new Pane(paneParams(items: [new Item, new Item])) [item1, item2] = pane.getItems() observed = [] @@ -351,14 +361,14 @@ describe "Pane", -> describe "when an item emits a destroyed event", -> it "removes it from the list of items", -> - pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C")])) [item1, item2, item3] = pane.getItems() pane.itemAtIndex(1).destroy() expect(pane.getItems()).toEqual [item1, item3] describe "::destroyInactiveItems()", -> it "destroys all items but the active item", -> - pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C")])) [item1, item2, item3] = pane.getItems() pane.activateItem(item2) pane.destroyInactiveItems() @@ -368,7 +378,7 @@ describe "Pane", -> pane = null beforeEach -> - pane = new Pane(items: [new Item("A")]) + pane = new Pane(paneParams(items: [new Item("A")])) spyOn(atom, 'showSaveDialogSync').andReturn('/selected/path') describe "when the active item has a uri", -> @@ -423,7 +433,7 @@ describe "Pane", -> pane = null beforeEach -> - pane = new Pane(items: [new Item("A")]) + pane = new Pane(paneParams(items: [new Item("A")])) spyOn(atom, 'showSaveDialogSync').andReturn('/selected/path') describe "when the current item has a saveAs method", -> @@ -461,7 +471,7 @@ describe "Pane", -> describe "::itemForURI(uri)", -> it "returns the item for which a call to .getURI() returns the given uri", -> - pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C"), new Item("D")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C"), new Item("D")])) [item1, item2, item3] = pane.getItems() item1.uri = "a" item2.uri = "b" @@ -473,7 +483,7 @@ describe "Pane", -> [pane, item1, item2, item3, item4] = [] beforeEach -> - pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C"), new Item("D")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C"), new Item("D")])) [item1, item2, item3, item4] = pane.getItems() it "moves the item to the given index and invokes ::onDidMoveItem observers", -> @@ -502,7 +512,7 @@ describe "Pane", -> [item1, item2, item3, item4, item5] = [] beforeEach -> - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(config: atom.config, confirm: confirm) pane1 = container.getActivePane() pane1.addItems([new Item("A"), new Item("B"), new Item("C")]) pane2 = pane1.splitRight(items: [new Item("D"), new Item("E")]) @@ -555,7 +565,7 @@ describe "Pane", -> [pane1, container] = [] beforeEach -> - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(config: atom.config, confirm: confirm, deserializerManager: atom.deserializers) pane1 = container.getActivePane() pane1.addItem(new Item("A")) @@ -655,32 +665,32 @@ describe "Pane", -> describe "::close()", -> it "prompts to save unsaved items before destroying the pane", -> - pane = new Pane(items: [new Item("A"), new Item("B")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B")])) [item1, item2] = pane.getItems() item1.shouldPromptToSave = -> true item1.getURI = -> "/test/path" item1.save = jasmine.createSpy("save") - spyOn(atom, 'confirm').andReturn(0) + confirm.andReturn(0) pane.close() - expect(atom.confirm).toHaveBeenCalled() + expect(confirm).toHaveBeenCalled() expect(item1.save).toHaveBeenCalled() expect(pane.isDestroyed()).toBe true it "does not destroy the pane if cancel is called", -> - pane = new Pane(items: [new Item("A"), new Item("B")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B")])) [item1, item2] = pane.getItems() item1.shouldPromptToSave = -> true item1.getURI = -> "/test/path" item1.save = jasmine.createSpy("save") - spyOn(atom, 'confirm').andReturn(1) + confirm.andReturn(1) pane.close() - expect(atom.confirm).toHaveBeenCalled() + expect(confirm).toHaveBeenCalled() expect(item1.save).not.toHaveBeenCalled() expect(pane.isDestroyed()).toBe false @@ -688,7 +698,7 @@ describe "Pane", -> [container, pane1, pane2] = [] beforeEach -> - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(config: atom.config, confirm: confirm) pane1 = container.root pane1.addItems([new Item("A"), new Item("B")]) pane2 = pane1.splitRight() @@ -735,10 +745,10 @@ describe "Pane", -> pane = null beforeEach -> - params = + pane = new Pane(paneParams( items: [new Item("A", "a"), new Item("B", "b"), new Item("C", "c")] flexScale: 2 - pane = new Pane(params) + )) it "can serialize and deserialize the pane and all its items", -> newPane = Pane.deserialize(pane.serialize(), atom) diff --git a/spec/window-event-handler-spec.coffee b/spec/window-event-handler-spec.coffee index 07bcae5a3..dd3b6031a 100644 --- a/spec/window-event-handler-spec.coffee +++ b/spec/window-event-handler-spec.coffee @@ -4,6 +4,7 @@ fs = require 'fs-plus' temp = require 'temp' TextEditor = require '../src/text-editor' WindowEventHandler = require '../src/window-event-handler' +ipc = require 'ipc' describe "WindowEventHandler", -> [projectPath, windowEventHandler] = [] @@ -50,64 +51,25 @@ describe "WindowEventHandler", -> describe "beforeunload event", -> beforeEach -> jasmine.unspy(TextEditor.prototype, "shouldPromptToSave") + spyOn(ipc, 'send') describe "when pane items are modified", -> - it "prompts user to save and calls atom.workspace.confirmClose", -> - editor = null - spyOn(atom.workspace, 'confirmClose').andCallThrough() - spyOn(atom, "confirm").andReturn(2) + editor = null + beforeEach -> + waitsForPromise -> atom.workspace.open("sample.js").then (o) -> editor = o + runs -> editor.insertText("I look different, I feel different.") - waitsForPromise -> - atom.workspace.open("sample.js").then (o) -> editor = o + it "prompts the user to save them, and allows the unload to continue if they confirm", -> + spyOn(atom.workspace, 'confirmClose').andReturn(true) + window.dispatchEvent(new CustomEvent('beforeunload')) + expect(atom.workspace.confirmClose).toHaveBeenCalled() + expect(ipc.send).not.toHaveBeenCalledWith('cancel-window-close') - runs -> - editor.insertText("I look different, I feel different.") - window.dispatchEvent(new CustomEvent('beforeunload')) - expect(atom.workspace.confirmClose).toHaveBeenCalled() - expect(atom.confirm).toHaveBeenCalled() - - it "prompts user to save and handler returns true if don't save", -> - editor = null - spyOn(atom, "confirm").andReturn(2) - - waitsForPromise -> - atom.workspace.open("sample.js").then (o) -> editor = o - - runs -> - editor.insertText("I look different, I feel different.") - window.dispatchEvent(new CustomEvent('beforeunload')) - expect(atom.confirm).toHaveBeenCalled() - - it "prompts user to save and handler returns false if dialog is canceled", -> - editor = null - spyOn(atom, "confirm").andReturn(1) - waitsForPromise -> - atom.workspace.open("sample.js").then (o) -> editor = o - - runs -> - editor.insertText("I look different, I feel different.") - window.dispatchEvent(new CustomEvent('beforeunload')) - expect(atom.confirm).toHaveBeenCalled() - - describe "when the same path is modified in multiple panes", -> - it "prompts to save the item", -> - return - editor = null - filePath = path.join(temp.mkdirSync('atom-file'), 'file.txt') - fs.writeFileSync(filePath, 'hello') - spyOn(atom.workspace, 'confirmClose').andCallThrough() - spyOn(atom, 'confirm').andReturn(0) - - waitsForPromise -> - atom.workspace.open(filePath).then (o) -> editor = o - - runs -> - atom.workspace.getActivePane().splitRight(copyActiveItem: true) - editor.setText('world') - window.dispatchEvent(new CustomEvent('beforeunload')) - expect(atom.workspace.confirmClose).toHaveBeenCalled() - expect(atom.confirm.callCount).toBe 1 - expect(fs.readFileSync(filePath, 'utf8')).toBe 'world' + it "cancels the unload if the user selects cancel", -> + spyOn(atom.workspace, 'confirmClose').andReturn(false) + window.dispatchEvent(new CustomEvent('beforeunload')) + expect(atom.workspace.confirmClose).toHaveBeenCalled() + expect(ipc.send).toHaveBeenCalledWith('cancel-window-close') describe "when a link is clicked", -> it "opens the http/https links in an external application", -> diff --git a/spec/workspace-spec.coffee b/spec/workspace-spec.coffee index b39570db0..fc5fb5fff 100644 --- a/spec/workspace-spec.coffee +++ b/spec/workspace-spec.coffee @@ -18,7 +18,7 @@ describe "Workspace", -> atom.project.setPaths([atom.project.getDirectories()[0]?.resolve('dir')]) atom.workspace = workspace = new Workspace({ config: atom.config, project: atom.project, packageManager: atom.packages, - notificationManager: atom.notifications, + notificationManager: atom.notifications, deserializerManager: atom.deserializers, clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion(), @@ -36,7 +36,7 @@ describe "Workspace", -> atom.project.deserialize(projectState, atom.deserializers) atom.workspace = new Workspace({ config: atom.config, project: atom.project, packageManager: atom.packages, - notificationManager: atom.notifications, + notificationManager: atom.notifications, deserializerManager: atom.deserializers, clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), setDocumentEdited: setDocumentEdited, assert: atom.assert.bind(atom) @@ -635,8 +635,8 @@ describe "Workspace", -> workspace2 = new Workspace({ config: atom.config, project: atom.project, packageManager: atom.packages, - notificationManager: atom.notifications, clipboard: atom.clipboard, - viewRegistry: atom.views, grammarRegistry: atom.grammars, + notificationManager: atom.notifications, deserializerManager: atom.deserializers, + clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion(), assert: atom.assert.bind(atom) @@ -695,8 +695,8 @@ describe "Workspace", -> document.title = null workspace2 = new Workspace({ config: atom.config, project: atom.project, packageManager: atom.packages, - notificationManager: atom.notifications, clipboard: atom.clipboard, - viewRegistry: atom.views, grammarRegistry: atom.grammars, + notificationManager: atom.notifications, deserializerManager: atom.deserializers, + clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion(), assert: atom.assert.bind(atom) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index e398df1f9..3445a0a49 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -172,7 +172,7 @@ class AtomEnvironment extends Model @commandInstaller = new CommandInstaller(@getVersion(), @confirm.bind(this)) @workspace = new Workspace({ - @config, @project, packageManager: @packages, grammarRegistry: @grammars, + @config, @project, packageManager: @packages, grammarRegistry: @grammars, deserializerManager: @deserializers, notificationManager: @notifications, setRepresentedFilename: @setRepresentedFilename.bind(this), setDocumentEdited: @setDocumentEdited.bind(this), @clipboard, viewRegistry: @views, assert: @assert.bind(this), confirm: @confirm.bind(this) }) diff --git a/src/pane-container.coffee b/src/pane-container.coffee index a91cee608..16a1274d6 100644 --- a/src/pane-container.coffee +++ b/src/pane-container.coffee @@ -13,12 +13,12 @@ class PaneContainer extends Model constructor: (params) -> super - {@config, @confirm} = params + {@config, notificationManager, deserializerManager, confirm} = params @emitter = new Emitter @subscriptions = new CompositeDisposable @itemRegistry = new ItemRegistry - @setRoot(new Pane({container: this, @config, @confirm})) + @setRoot(new Pane({container: this, @config, notificationManager, deserializerManager, confirm})) @setActivePane(@getRoot()) @monitorActivePaneItem() @monitorPaneItems() diff --git a/src/pane.coffee b/src/pane.coffee index f1af017de..beb6a4136 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -14,7 +14,7 @@ class Pane extends Model activeItem: undefined focused: false - @deserialize: (state, {deserializers}) -> + @deserialize: (state, {deserializers, config, notifications, confirm}) -> {items, activeItemURI, activeItemUri} = state activeItemURI ?= activeItemUri state.items = compact(items.map (itemState) -> deserializers.deserialize(itemState)) @@ -22,13 +22,20 @@ class Pane extends Model if typeof item.getURI is 'function' itemURI = item.getURI() itemURI is activeItemURI - new this(state) + new Pane(extend(state, { + deserializerManager: deserializers, + notificationManager: notifications, + confirm: confirm, + config: config + })) constructor: (params) -> super - @activeItem = params?.activeItem - @focused = params?.focused + { + @activeItem, @focused, @confirm, @notificationManager, @config, + @deserializerManager + } = params @emitter = new Emitter @itemSubscriptions = new WeakMap @@ -390,7 +397,7 @@ class Pane extends Model @items.splice(index, 1) @emitter.emit 'did-remove-item', {item, index, destroyed: not moved, moved} @container?.didDestroyPaneItem({item, index, pane: this}) unless moved - @destroy() if @items.length is 0 and atom.config.get('core.destroyEmptyPanes') + @destroy() if @items.length is 0 and @config.get('core.destroyEmptyPanes') # Public: Move the given item to the given index. # @@ -456,7 +463,7 @@ class Pane extends Model else return true - chosen = atom.confirm + chosen = @confirm message: "'#{item.getTitle?() ? uri}' has changes, do you want to save them?" detailedMessage: "Your changes will be lost if you close this item without saving." buttons: ["Save", "Cancel", "Don't Save"] @@ -549,7 +556,7 @@ class Pane extends Model copyActiveItem: -> if @activeItem? - @activeItem.copy?() ? atom.deserializers.deserialize(@activeItem.serialize()) + @activeItem.copy?() ? @deserializerManager.deserialize(@activeItem.serialize()) ### Section: Lifecycle @@ -641,7 +648,7 @@ class Pane extends Model @parent.replaceChild(this, new PaneAxis({@container, orientation, children: [this], @flexScale})) @setFlexScale(1) - newPane = new @constructor(params) + newPane = new Pane(extend({@confirm, @deserializerManager, @config}, params)) switch side when 'before' then @parent.insertChildBefore(this, newPane) when 'after' then @parent.insertChildAfter(this, newPane) @@ -683,12 +690,12 @@ class Pane extends Model handleSaveError: (error, item) -> itemPath = error.path ? item?.getPath?() - addWarningWithPath = (message, options) -> + addWarningWithPath = (message, options) => message = "#{message} '#{itemPath}'" if itemPath - atom.notifications.addWarning(message, options) + @notificationManager.addWarning(message, options) if error.code is 'EISDIR' or error.message?.endsWith?('is a directory') - atom.notifications.addWarning("Unable to save file: #{error.message}") + @notificationManager.addWarning("Unable to save file: #{error.message}") else if error.code is 'EACCES' addWarningWithPath('Unable to save file: Permission denied') else if error.code in ['EPERM', 'EBUSY', 'UNKNOWN', 'EEXIST'] @@ -711,6 +718,6 @@ class Pane extends Model addWarningWithPath('Unable to save file: Invalid seek') else if errorMatch = /ENOTDIR, not a directory '([^']+)'/.exec(error.message) fileName = errorMatch[1] - atom.notifications.addWarning("Unable to save file: A directory in the path '#{fileName}' could not be written to") + @notificationManager.addWarning("Unable to save file: A directory in the path '#{fileName}' could not be written to") else throw error diff --git a/src/workspace.coffee b/src/workspace.coffee index ff7f14738..6d87fbbf4 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -29,14 +29,14 @@ class Workspace extends Model { @packageManager, @config, @project, @grammarRegistry, @notificationManager, @clipboard, @viewRegistry, @grammarRegistry, @setRepresentedFilename, - @setDocumentEdited, @assert, @confirm + @setDocumentEdited, @assert, @confirm, deserializerManager } = params @emitter = new Emitter @openers = [] @destroyedItemURIs = [] - @paneContainer = new PaneContainer({@config, @confirm}) + @paneContainer = new PaneContainer({@config, @confirm, @notificationManager, deserializerManager}) @paneContainer.onDidDestroyPaneItem(@didDestroyPaneItem) @directorySearchers = []