Prompt user only once when quitting/restarting and canceling save dialog

I think this slipped through during the refactoring performed in
dc32018. With this commit we are fixing the regression and adding a new
main process regression test to exercise this behavior.
This commit is contained in:
Antonio Scandurra
2017-08-14 12:21:19 +02:00
parent 44441b14c3
commit 91b7c14281
2 changed files with 61 additions and 16 deletions

View File

@@ -14,10 +14,11 @@ const ATOM_RESOURCE_PATH = path.resolve(__dirname, '..', '..')
describe('AtomApplication', function () {
this.timeout(60 * 1000)
let originalAppQuit, originalAtomHome, atomApplicationsToDestroy
let originalAppQuit, originalShowMessageBox, originalAtomHome, atomApplicationsToDestroy
beforeEach(function () {
originalAppQuit = electron.app.quit
originalShowMessageBox = electron.dialog
mockElectronAppQuit()
originalAtomHome = process.env.ATOM_HOME
process.env.ATOM_HOME = makeTempDir('atom-home')
@@ -39,6 +40,7 @@ describe('AtomApplication', function () {
}
await clearElectronSession()
electron.app.quit = originalAppQuit
electron.dialog.showMessageBox = originalShowMessageBox
})
describe('launch', function () {
@@ -462,20 +464,42 @@ describe('AtomApplication', function () {
})
})
describe('before quitting', function () {
it('waits until all the windows have saved their state and then quits', async function () {
const dirAPath = makeTempDir("a")
const dirBPath = makeTempDir("b")
const atomApplication = buildAtomApplication()
const window1 = atomApplication.launch(parseCommandLine([path.join(dirAPath, 'file-a')]))
await focusWindow(window1)
const window2 = atomApplication.launch(parseCommandLine([path.join(dirBPath, 'file-b')]))
await focusWindow(window2)
electron.app.quit()
assert(!electron.app.hasQuitted())
await Promise.all([window1.lastPrepareToUnloadPromise, window2.lastPrepareToUnloadPromise])
assert(electron.app.hasQuitted())
it('waits until all the windows have saved their state before quitting', async function () {
const dirAPath = makeTempDir("a")
const dirBPath = makeTempDir("b")
const atomApplication = buildAtomApplication()
const window1 = atomApplication.launch(parseCommandLine([path.join(dirAPath, 'file-a')]))
await focusWindow(window1)
const window2 = atomApplication.launch(parseCommandLine([path.join(dirBPath, 'file-b')]))
await focusWindow(window2)
electron.app.quit()
assert(!electron.app.hasQuitted())
await Promise.all([window1.lastPrepareToUnloadPromise, window2.lastPrepareToUnloadPromise])
assert(electron.app.hasQuitted())
})
it.only('prevents quitting if user cancels when prompted to save an item', async () => {
const atomApplication = buildAtomApplication()
const window1 = atomApplication.launch(parseCommandLine([]))
const window2 = atomApplication.launch(parseCommandLine([]))
await Promise.all([window1.loadedPromise, window2.loadedPromise])
await evalInWebContents(window1.browserWindow.webContents, function (sendBackToMainProcess) {
atom.workspace.getActiveTextEditor().insertText('unsaved text')
sendBackToMainProcess()
})
// Choosing "Cancel"
mockElectronShowMessageBox({choice: 1})
electron.app.quit()
await atomApplication.lastBeforeQuitPromise
assert(!electron.app.hasQuitted())
assert.equal(electron.app.quit.callCount, 1) // Ensure choosing "Cancel" doesn't try to quit the electron app more than once (regression)
// Choosing "Don't save"
mockElectronShowMessageBox({choice: 2})
electron.app.quit()
await atomApplication.lastBeforeQuitPromise
assert(electron.app.hasQuitted())
})
function buildAtomApplication () {
@@ -496,6 +520,12 @@ describe('AtomApplication', function () {
function mockElectronAppQuit () {
let quitted = false
electron.app.quit = function () {
if (electron.app.quit.callCount) {
electron.app.quit.callCount++
} else {
electron.app.quit.callCount = 1
}
let shouldQuit = true
electron.app.emit('before-quit', {preventDefault: () => { shouldQuit = false }})
if (shouldQuit) {
@@ -507,6 +537,12 @@ describe('AtomApplication', function () {
}
}
function mockElectronShowMessageBox ({choice}) {
electron.dialog.showMessageBox = function () {
return choice
}
}
function makeTempDir (name) {
const temp = require('temp').track()
return fs.realpathSync(temp.mkdirSync(name))

View File

@@ -269,10 +269,19 @@ class AtomApplication
@openPathOnEvent('application:open-license', path.join(process.resourcesPath, 'LICENSE.md'))
@disposable.add ipcHelpers.on app, 'before-quit', (event) =>
unless @quitting
resolveBeforeQuitPromise = null
@lastBeforeQuitPromise = new Promise((resolve) -> resolveBeforeQuitPromise = resolve)
if @quitting
resolveBeforeQuitPromise()
else
event.preventDefault()
@quitting = true
Promise.all(@windows.map((window) -> window.prepareToUnload())).then(-> app.quit())
windowUnloadPromises = @windows.map((window) -> window.prepareToUnload())
Promise.all(windowUnloadPromises).then((windowUnloadedResults) ->
didUnloadAllWindows = windowUnloadedResults.every((didUnloadWindow) -> didUnloadWindow)
app.quit() if didUnloadAllWindows
resolveBeforeQuitPromise()
)
@disposable.add ipcHelpers.on app, 'will-quit', =>
@killAllProcesses()