Skip to content
This repository was archived by the owner on Dec 15, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 8 additions & 10 deletions lib/autosave.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@ module.exports = {
activate () {
this.subscriptions = new CompositeDisposable()

const handleBeforeUnload = this.autosaveAllPaneItems.bind(this)

window.addEventListener('beforeunload', handleBeforeUnload, true)
this.subscriptions.add(new Disposable(function () { return window.removeEventListener('beforeunload', handleBeforeUnload, true) }))

const handleBlur = event => {
if (event.target === window) {
this.autosaveAllPaneItems()
Expand All @@ -35,6 +30,7 @@ module.exports = {

deactivate () {
this.subscriptions.dispose()
return this.autosaveAllPaneItems()
},

autosavePaneItem (paneItem, create = false) {
Expand All @@ -54,16 +50,18 @@ module.exports = {
}

const pane = atom.workspace.paneForItem(paneItem)
let promise = Promise.resolve()
if (pane) {
return pane.saveItem(paneItem)
promise = pane.saveItem(paneItem)
} else if (typeof paneItem.save === 'function') {
return paneItem.save()
} else {
return Promise.resolve()
promise = paneItem.save()
}
return promise
},

autosaveAllPaneItems () {
return atom.workspace.getPaneItems().map((paneItem) => this.autosavePaneItem(paneItem))
return Promise.all(
atom.workspace.getPaneItems().map((paneItem) => this.autosavePaneItem(paneItem))
)
}
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"beforeEach",
"jasmine",
"waitsForPromise",
"waitsFor",
"runs",
"spyOn",
"FocusEvent",
Expand Down
66 changes: 61 additions & 5 deletions spec/autosave-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ describe('Autosave', () => {

otherItem2 = otherItem1.copy()

spyOn(initialActiveItem, 'save')
spyOn(otherItem1, 'save')
spyOn(otherItem2, 'save')
spyOn(initialActiveItem, 'save').andCallFake(() => Promise.resolve())
spyOn(otherItem1, 'save').andCallFake(() => Promise.resolve())
spyOn(otherItem2, 'save').andCallFake(() => Promise.resolve())
})

describe('when the item is not modified', () => {
it('autosaves newly added items', async () => {
atom.config.set('autosave.enabled', true)
spyOn(atom.workspace.getActivePane(), 'saveItem')
spyOn(atom.workspace.getActivePane(), 'saveItem').andCallFake(() => Promise.resolve())
const newItem = await atom.workspace.open('notyet.coffee')

expect(atom.workspace.getActivePane().saveItem).toHaveBeenCalledWith(newItem)
Expand Down Expand Up @@ -172,6 +172,61 @@ describe('Autosave', () => {
})
})

describe('when the package is deactivated', () => {
it('saves all items and waits for saves to complete', () => {
atom.config.set('autosave.enabled', true)

const leftPane = atom.workspace.getActivePane()
leftPane.splitRight({items: [otherItem1]})

initialActiveItem.insertText('a')
otherItem1.insertText('b')

let deactivated = false
let asyncDeactivateSupported = true
let resolveInitial = () => {}
let resolveOther = () => {}
initialActiveItem.save.andCallFake(() => {
return new Promise(resolve => {
resolveInitial = resolve
})
})
otherItem1.save.andCallFake(() => {
return new Promise(resolve => {
resolveOther = resolve
})
})

let deactivatePromise = atom.packages.deactivatePackage('autosave')
if (!deactivatePromise || !deactivatePromise.then || typeof deactivatePromise.then !== 'function') {
// Atom does not support asynchronous package deactivation.
// This keeps us from failing on 1.20
asyncDeactivateSupported = false
deactivatePromise = Promise.resolve()
}
deactivatePromise.then((result) => {
if (result === undefined) {
// This keeps us from failing on 1.21-beta1
asyncDeactivateSupported = false
}
deactivated = true
})

waitsForPromise(() => Promise.resolve())

runs(() => {
if (asyncDeactivateSupported) {
expect(deactivated).toBe(false)
}

resolveInitial()
resolveOther()
})

waitsFor(() => !asyncDeactivateSupported || deactivated)
})
})

it("saves via the item's Pane so that write errors are handled via notifications", async () => {
const saveError = new Error('Save failed')
saveError.code = 'EACCES'
Expand All @@ -180,13 +235,14 @@ describe('Autosave', () => {

const errorCallback = jasmine.createSpy('errorCallback').andCallFake(({preventDefault}) => preventDefault())
atom.onWillThrowError(errorCallback)
spyOn(atom.notifications, 'addWarning')

initialActiveItem.insertText('a')
atom.config.set('autosave.enabled', true)

await atom.workspace.destroyActivePaneItem()
expect(initialActiveItem.save).toHaveBeenCalled()
expect(errorCallback.callCount).toBe(1)
expect(atom.notifications.addWarning.callCount > 0 || errorCallback.callCount > 0).toBe(true)
})

describe('dontSaveIf service', () => {
Expand Down