mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-09-19 23:17:16 +03:00
407 lines
14 KiB
JavaScript
407 lines
14 KiB
JavaScript
/* globals assert */
|
|
|
|
const path = require('path')
|
|
const fs = require('fs-plus')
|
|
const url = require('url')
|
|
const {EventEmitter} = require('events')
|
|
const temp = require('temp').track()
|
|
const {sandbox} = require('sinon')
|
|
const dedent = require('dedent')
|
|
|
|
const AtomWindow = require('../../src/main-process/atom-window')
|
|
const {emitterEventPromise} = require('../async-spec-helpers')
|
|
|
|
describe('AtomWindow', function () {
|
|
let sinon, app, service
|
|
|
|
beforeEach(function () {
|
|
sinon = sandbox.create()
|
|
app = new StubApplication(sinon)
|
|
service = new StubRecoveryService(sinon)
|
|
})
|
|
|
|
afterEach(function () {
|
|
sinon.restore()
|
|
})
|
|
|
|
describe('creating a real window', function () {
|
|
let resourcePath, windowInitializationScript, atomHome
|
|
let original
|
|
|
|
this.timeout(10 * 1000)
|
|
|
|
beforeEach(async function () {
|
|
original = {
|
|
ATOM_HOME: process.env.ATOM_HOME,
|
|
ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: process.env.ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT
|
|
}
|
|
|
|
resourcePath = path.resolve(__dirname, '../..')
|
|
|
|
windowInitializationScript = require.resolve(
|
|
path.join(resourcePath, 'src/initialize-application-window')
|
|
)
|
|
|
|
atomHome = await new Promise((resolve, reject) => {
|
|
temp.mkdir('launch-', (err, rootPath) => {
|
|
if (err) { reject(err) } else { resolve(rootPath) }
|
|
})
|
|
})
|
|
|
|
await new Promise((resolve, reject) => {
|
|
const config = dedent`
|
|
'*':
|
|
core:
|
|
automaticallyUpdate: false
|
|
telemetryConsent: "no"
|
|
welcome:
|
|
showOnStartup: false
|
|
`
|
|
|
|
fs.writeFile(path.join(atomHome, 'config.cson'), config, {encoding: 'utf8'}, err => {
|
|
if (err) { reject(err) } else { resolve() }
|
|
})
|
|
})
|
|
|
|
await new Promise((resolve, reject) => {
|
|
fs.symlink(
|
|
path.join(original.ATOM_HOME, 'compile-cache'),
|
|
path.join(atomHome, 'compile-cache'),
|
|
'junction',
|
|
err => { if (err) { reject(err) } else { resolve() } }
|
|
)
|
|
})
|
|
|
|
process.env.ATOM_HOME = atomHome
|
|
process.env.ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT = 'true'
|
|
})
|
|
|
|
afterEach(async function () {
|
|
process.env.ATOM_HOME = original.ATOM_HOME
|
|
process.env.ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT = original.ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT
|
|
})
|
|
|
|
it('creates a real, properly configured BrowserWindow', async function () {
|
|
const w = new AtomWindow(app, service, {
|
|
resourcePath,
|
|
windowInitializationScript,
|
|
headless: true,
|
|
extra: 'extra-load-setting'
|
|
})
|
|
const {browserWindow} = w
|
|
|
|
assert.isFalse(browserWindow.isVisible())
|
|
assert.strictEqual(browserWindow.getTitle(), 'Atom')
|
|
|
|
const settings = JSON.parse(browserWindow.loadSettingsJSON)
|
|
assert.strictEqual(settings.userSettings, 'stub-config')
|
|
assert.strictEqual(settings.extra, 'extra-load-setting')
|
|
assert.strictEqual(settings.resourcePath, resourcePath)
|
|
assert.strictEqual(settings.atomHome, atomHome)
|
|
assert.isFalse(settings.devMode)
|
|
assert.isFalse(settings.safeMode)
|
|
assert.isFalse(settings.clearWindowState)
|
|
|
|
await emitterEventPromise(browserWindow, 'ready-to-show')
|
|
|
|
assert.strictEqual(browserWindow.webContents.getURL(), url.format({
|
|
protocol: 'file',
|
|
pathname: path.join(resourcePath, 'static/index.html'),
|
|
slashes: true
|
|
}))
|
|
})
|
|
})
|
|
|
|
describe('launch behavior', function () {
|
|
if (process.platform === 'darwin') {
|
|
it('sets titleBarStyle to "hidden" for a custom title bar on non-spec windows', function () {
|
|
app.config['core.titleBar'] = 'custom'
|
|
|
|
const {browserWindow: w0} = new AtomWindow(app, service, {
|
|
browserWindowConstructor: StubBrowserWindow
|
|
})
|
|
assert.strictEqual(w0.options.titleBarStyle, 'hidden')
|
|
|
|
const {browserWindow: w1} = new AtomWindow(app, service, {
|
|
browserWindowConstructor: StubBrowserWindow,
|
|
isSpec: true
|
|
})
|
|
assert.isUndefined(w1.options.titleBarStyle)
|
|
})
|
|
|
|
it('sets titleBarStyle to "hiddenInset" for a custom inset title bar on non-spec windows', function () {
|
|
app.config['core.titleBar'] = 'custom-inset'
|
|
|
|
const {browserWindow: w0} = new AtomWindow(app, service, {
|
|
browserWindowConstructor: StubBrowserWindow
|
|
})
|
|
assert.strictEqual(w0.options.titleBarStyle, 'hiddenInset')
|
|
|
|
const {browserWindow: w1} = new AtomWindow(app, service, {
|
|
browserWindowConstructor: StubBrowserWindow,
|
|
isSpec: true
|
|
})
|
|
assert.isUndefined(w1.options.titleBarStyle)
|
|
})
|
|
|
|
it('sets frame to "false" for a hidden title bar on non-spec windows', function () {
|
|
app.config['core.titleBar'] = 'hidden'
|
|
|
|
const {browserWindow: w0} = new AtomWindow(app, service, {
|
|
browserWindowConstructor: StubBrowserWindow
|
|
})
|
|
assert.isFalse(w0.options.frame)
|
|
|
|
const {browserWindow: w1} = new AtomWindow(app, service, {
|
|
browserWindowConstructor: StubBrowserWindow,
|
|
isSpec: true
|
|
})
|
|
assert.isUndefined(w1.options.frame)
|
|
})
|
|
} else {
|
|
it('ignores title bar style settings', function () {
|
|
for (const value of ['custom', 'custom-inset', 'hidden']) {
|
|
app.config['core.titleBar'] = value
|
|
const {browserWindow} = new AtomWindow(app, service, {
|
|
browserWindowConstructor: StubBrowserWindow
|
|
})
|
|
assert.isUndefined(browserWindow.options.titleBarStyle)
|
|
assert.isUndefined(browserWindow.options.frame)
|
|
}
|
|
})
|
|
}
|
|
|
|
it('opens initial locations', async function () {
|
|
const locationsToOpen = [
|
|
{
|
|
pathToOpen: 'file.txt',
|
|
initialLine: 1,
|
|
initialColumn: 2,
|
|
mustBeDirectory: false,
|
|
forceAddToWindow: false,
|
|
hasWaitSession: false
|
|
},
|
|
{
|
|
pathToOpen: '/directory',
|
|
initialLine: null,
|
|
initialColumn: null,
|
|
mustBeDirectory: true,
|
|
forceAddToWindow: false,
|
|
hasWaitSession: false
|
|
}
|
|
]
|
|
|
|
const w = new AtomWindow(app, service, { browserWindowConstructor: StubBrowserWindow, locationsToOpen })
|
|
|
|
const loadPromise = emitterEventPromise(w, 'window:loaded')
|
|
w.browserWindow.emit('window:loaded')
|
|
await loadPromise
|
|
|
|
assert.deepEqual(w.browserWindow.sent, [['message', 'open-locations', locationsToOpen]])
|
|
})
|
|
|
|
it('does not open an initial null location', async function () {
|
|
const w = new AtomWindow(app, service, {
|
|
browserWindowConstructor: StubBrowserWindow,
|
|
locationsToOpen: [{ pathToOpen: null }]
|
|
})
|
|
|
|
const loadPromise = emitterEventPromise(w, 'window:loaded')
|
|
w.browserWindow.emit('window:loaded')
|
|
await loadPromise
|
|
|
|
assert.lengthOf(w.browserWindow.sent, 0)
|
|
})
|
|
|
|
it('does not open initial locations in spec mode', async function () {
|
|
const w = new AtomWindow(app, service, {
|
|
browserWindowConstructor: StubBrowserWindow,
|
|
locationsToOpen: [{ pathToOpen: 'file.txt' }],
|
|
isSpec: true
|
|
})
|
|
|
|
const loadPromise = emitterEventPromise(w, 'window:loaded')
|
|
w.browserWindow.emit('window:loaded')
|
|
await loadPromise
|
|
|
|
assert.lengthOf(w.browserWindow.sent, 0)
|
|
})
|
|
|
|
it('focuses the webView for specs', function () {
|
|
const w = new AtomWindow(app, service, {
|
|
browserWindowConstructor: StubBrowserWindow,
|
|
isSpec: true
|
|
})
|
|
|
|
assert.isTrue(w.browserWindow.behavior.focusOnWebView)
|
|
})
|
|
})
|
|
|
|
describe('project root tracking', function () {
|
|
it('knows when it has no roots', function () {
|
|
const w = new AtomWindow(app, service, { browserWindowConstructor: StubBrowserWindow })
|
|
assert.isFalse(w.hasProjectPaths())
|
|
})
|
|
|
|
it('is initialized from directories in the initial locationsToOpen', function () {
|
|
const locationsToOpen = [
|
|
{ pathToOpen: 'file.txt', exists: true, isFile: true },
|
|
{ pathToOpen: 'directory0', exists: true, isDirectory: true },
|
|
{ pathToOpen: 'directory1', exists: true, isDirectory: true },
|
|
{ pathToOpen: 'new-file.txt' },
|
|
{ pathToOpen: null }
|
|
]
|
|
|
|
const w = new AtomWindow(app, service, { browserWindowConstructor: StubBrowserWindow, locationsToOpen })
|
|
|
|
assert.deepEqual(w.projectRoots, ['directory0', 'directory1'])
|
|
assert.deepEqual(w.loadSettings.initialProjectRoots, ['directory0', 'directory1'])
|
|
assert.isTrue(w.hasProjectPaths())
|
|
})
|
|
|
|
it('is updated by setProjectRoots', function () {
|
|
const locationsToOpen = [
|
|
{ pathToOpen: 'directory0', exists: true, isDirectory: true }
|
|
]
|
|
|
|
const w = new AtomWindow(app, service, { browserWindowConstructor: StubBrowserWindow, locationsToOpen })
|
|
assert.deepEqual(w.projectRoots, ['directory0'])
|
|
assert.deepEqual(w.loadSettings.initialProjectRoots, ['directory0'])
|
|
|
|
w.setProjectRoots(['directory1', 'directory0', 'directory2'])
|
|
assert.deepEqual(w.projectRoots, ['directory0', 'directory1', 'directory2'])
|
|
assert.deepEqual(w.loadSettings.initialProjectRoots, ['directory0', 'directory1', 'directory2'])
|
|
})
|
|
|
|
it('never reports that it owns the empty path', function () {
|
|
const locationsToOpen = [
|
|
{ pathToOpen: 'directory0', exists: true, isDirectory: true },
|
|
{ pathToOpen: 'directory1', exists: true, isDirectory: true },
|
|
{ pathToOpen: null }
|
|
]
|
|
|
|
const w = new AtomWindow(app, service, { browserWindowConstructor: StubBrowserWindow, locationsToOpen })
|
|
assert.isFalse(w.containsLocation({pathToOpen: null}))
|
|
})
|
|
|
|
it('discovers an exact path match', function () {
|
|
const locationsToOpen = [
|
|
{ pathToOpen: 'directory0', exists: true, isDirectory: true },
|
|
{ pathToOpen: 'directory1', exists: true, isDirectory: true }
|
|
]
|
|
const w = new AtomWindow(app, service, { browserWindowConstructor: StubBrowserWindow, locationsToOpen })
|
|
|
|
assert.isTrue(w.containsLocation({pathToOpen: 'directory0'}))
|
|
assert.isFalse(w.containsLocation({pathToOpen: 'directory2'}))
|
|
})
|
|
|
|
it('discovers the path of a file within any project root', function () {
|
|
const locationsToOpen = [
|
|
{ pathToOpen: 'directory0', exists: true, isDirectory: true },
|
|
{ pathToOpen: 'directory1', exists: true, isDirectory: true }
|
|
]
|
|
const w = new AtomWindow(app, service, { browserWindowConstructor: StubBrowserWindow, locationsToOpen })
|
|
|
|
assert.isTrue(w.containsLocation({
|
|
pathToOpen: path.join('directory0/file-0.txt'), exists: true, isFile: true
|
|
}))
|
|
assert.isTrue(w.containsLocation({
|
|
pathToOpen: path.join('directory0/deep/file-0.txt'), exists: true, isFile: true
|
|
}))
|
|
assert.isFalse(w.containsLocation({
|
|
pathToOpen: path.join('directory2/file-9.txt'), exists: true, isFile: true
|
|
}))
|
|
assert.isFalse(w.containsLocation({
|
|
pathToOpen: path.join('directory2/deep/file-9.txt'), exists: true, isFile: true
|
|
}))
|
|
})
|
|
|
|
it('reports that it owns nonexistent paths within a project root', function () {
|
|
const locationsToOpen = [
|
|
{ pathToOpen: 'directory0', exists: true, isDirectory: true },
|
|
{ pathToOpen: 'directory1', exists: true, isDirectory: true }
|
|
]
|
|
const w = new AtomWindow(app, service, { browserWindowConstructor: StubBrowserWindow, locationsToOpen })
|
|
|
|
assert.isTrue(w.containsLocation({ pathToOpen: path.join('directory0/file-1.txt'), exists: false }))
|
|
assert.isTrue(w.containsLocation({ pathToOpen: path.join('directory1/subdir/file-0.txt'), exists: false }))
|
|
})
|
|
|
|
it('never reports that it owns directories within a project root', function () {
|
|
const locationsToOpen = [
|
|
{ pathToOpen: 'directory0', exists: true, isDirectory: true },
|
|
{ pathToOpen: 'directory1', exists: true, isDirectory: true }
|
|
]
|
|
const w = new AtomWindow(app, service, { browserWindowConstructor: StubBrowserWindow, locationsToOpen })
|
|
|
|
assert.isFalse(w.containsLocation({
|
|
pathToOpen: path.join('directory0/subdir-0'), exists: true, isDirectory: true
|
|
}))
|
|
})
|
|
|
|
it('checks a full list of paths and reports if it owns all of them', function () {
|
|
const locationsToOpen = [
|
|
{ pathToOpen: 'directory0', exists: true, isDirectory: true },
|
|
{ pathToOpen: 'directory1', exists: true, isDirectory: true }
|
|
]
|
|
const w = new AtomWindow(app, service, { browserWindowConstructor: StubBrowserWindow, locationsToOpen })
|
|
|
|
assert.isTrue(w.containsLocations([
|
|
{ pathToOpen: 'directory0' },
|
|
{ pathToOpen: path.join('directory1/file-0.txt'), exists: true, isFile: true }
|
|
]))
|
|
assert.isFalse(w.containsLocations([
|
|
{ pathToOpen: 'directory2' },
|
|
{ pathToOpen: 'directory0' }
|
|
]))
|
|
assert.isFalse(w.containsLocations([
|
|
{ pathToOpen: 'directory2' },
|
|
{ pathToOpen: 'directory1' }
|
|
]))
|
|
})
|
|
})
|
|
})
|
|
|
|
class StubApplication {
|
|
constructor (sinon) {
|
|
this.config = {
|
|
'core.titleBar': 'native',
|
|
get: key => this.config[key] || null
|
|
}
|
|
this.configFile = {
|
|
get () { return 'stub-config' }
|
|
}
|
|
|
|
this.removeWindow = sinon.spy()
|
|
this.saveCurrentWindowOptions = sinon.spy()
|
|
}
|
|
}
|
|
|
|
class StubRecoveryService {
|
|
constructor (sinon) {
|
|
this.didCloseWindow = sinon.spy()
|
|
this.didCrashWindow = sinon.spy()
|
|
}
|
|
}
|
|
|
|
class StubBrowserWindow extends EventEmitter {
|
|
constructor (options) {
|
|
super()
|
|
this.options = options
|
|
this.sent = []
|
|
this.behavior = {
|
|
focusOnWebView: false
|
|
}
|
|
|
|
this.webContents = new EventEmitter()
|
|
this.webContents.send = (...args) => { this.sent.push(args) }
|
|
this.webContents.setVisualZoomLevelLimits = () => {}
|
|
}
|
|
|
|
loadURL () {}
|
|
|
|
focusOnWebView () {
|
|
this.behavior.focusOnWebView = true
|
|
}
|
|
}
|