mirror of
https://github.com/atom/atom.git
synced 2026-04-28 03:01:47 -04:00
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:
@@ -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))
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user