diff --git a/spec-main/api-browser-window-spec.ts b/spec-main/api-browser-window-spec.ts index b51075a878df..8dd2b1860117 100644 --- a/spec-main/api-browser-window-spec.ts +++ b/spec-main/api-browser-window-spec.ts @@ -5,16 +5,49 @@ import * as fs from 'fs' import * as qs from 'querystring' import * as http from 'http' import { AddressInfo } from 'net' -import { app, BrowserWindow, ipcMain, OnBeforeSendHeadersListenerDetails } from 'electron' +import { app, BrowserWindow, ipcMain, OnBeforeSendHeadersListenerDetails, screen } from 'electron' import { emittedOnce } from './events-helpers'; import { closeWindow } from './window-helpers'; const { expect } = chai +const ifit = (condition: boolean) => (condition ? it : it.skip) +const ifdescribe = (condition: boolean) => (condition ? describe : describe.skip) + chai.use(chaiAsPromised) const fixtures = path.resolve(__dirname, '..', 'spec', 'fixtures') +// Is the display's scale factor possibly causing rounding of pixel coordinate +// values? +const isScaleFactorRounding = () => { + const { scaleFactor } = screen.getPrimaryDisplay() + // Return true if scale factor is non-integer value + if (Math.round(scaleFactor) !== scaleFactor) return true + // Return true if scale factor is odd number above 2 + return scaleFactor > 2 && scaleFactor % 2 === 1 +} + +const expectBoundsEqual = (actual: any, expected: any) => { + if (!isScaleFactorRounding()) { + expect(expected).to.deep.equal(actual) + } else if (Array.isArray(actual)) { + expect(actual[0]).to.be.closeTo(expected[0], 1) + expect(actual[1]).to.be.closeTo(expected[1], 1) + } else { + expect(actual.x).to.be.closeTo(expected.x, 1) + expect(actual.y).to.be.closeTo(expected.y, 1) + expect(actual.width).to.be.closeTo(expected.width, 1) + expect(actual.height).to.be.closeTo(expected.height, 1) + } +} + +const closeAllWindows = async () => { + for (const w of BrowserWindow.getAllWindows()) { + await closeWindow(w, {assertNotWindows: false}) + } +} + describe('BrowserWindow module', () => { describe('BrowserWindow constructor', () => { it('allows passing void 0 as the webContents', async () => { @@ -452,12 +485,12 @@ describe('BrowserWindow module', () => { w.loadURL(`${url}/302`) }) - it.skip('can be prevented', (done) => { + it('can be prevented', (done) => { w.webContents.once('will-redirect', (event) => { event.preventDefault() }) - w.webContents.on('will-navigate', (e, url) => { - expect(url).to.equal(`${url}/302`) + w.webContents.on('will-navigate', (e, u) => { + expect(u).to.equal(`${url}/302`) }) w.webContents.on('did-stop-loading', () => { expect(w.webContents.getURL()).to.equal( @@ -466,73 +499,569 @@ describe('BrowserWindow module', () => { ) done() }) - w.webContents.on('will-redirect', (e, url) => { - expect(url).to.equal(`${url}/200`) + w.webContents.on('will-redirect', (e, u) => { + expect(u).to.equal(`${url}/200`) }) w.loadURL(`${url}/navigate-302`) }) }) }) - describe('BrowserWindow.show()', () => { + describe('focus and visibility', () => { let w = null as unknown as BrowserWindow beforeEach(() => { - w = new BrowserWindow({show: false, webPreferences: {nodeIntegration: true}}) + w = new BrowserWindow({show: false}) }) afterEach(async () => { await closeWindow(w) w = null as unknown as BrowserWindow }) - it('should focus on window', () => { - w.show() - if (process.platform === 'darwin' && !isCI) { - // on CI, the Electron window will be the only one open, so it'll get - // focus. on not-CI, some other window will have focus, and we don't - // steal focus any more, so we expect isFocused to be false. - expect(w.isFocused()).to.equal(false) - } else { - expect(w.isFocused()).to.equal(true) - } - }) - it('should make the window visible', () => { - w.show() - expect(w.isVisible()).to.equal(true) - }) - it('emits when window is shown', (done) => { - w.once('show', () => { - expect(w.isVisible()).to.equal(true) - done() + + describe('BrowserWindow.show()', () => { + it('should focus on window', () => { + w.show() + if (process.platform === 'darwin' && !isCI) { + // on CI, the Electron window will be the only one open, so it'll get + // focus. on not-CI, some other window will have focus, and we don't + // steal focus any more, so we expect isFocused to be false. + expect(w.isFocused()).to.equal(false) + } else { + expect(w.isFocused()).to.equal(true) + } + }) + it('should make the window visible', () => { + w.show() + expect(w.isVisible()).to.equal(true) + }) + it('emits when window is shown', (done) => { + w.once('show', () => { + expect(w.isVisible()).to.equal(true) + done() + }) + w.show() + }) + }) + + describe('BrowserWindow.hide()', () => { + it('should defocus on window', () => { + w.hide() + expect(w.isFocused()).to.equal(false) + }) + it('should make the window not visible', () => { + w.show() + w.hide() + expect(w.isVisible()).to.equal(false) + }) + it('emits when window is hidden', async () => { + const shown = emittedOnce(w, 'show') + w.show() + await shown + const hidden = emittedOnce(w, 'hide') + w.hide() + await hidden + expect(w.isVisible()).to.equal(false) + }) + }) + + describe('BrowserWindow.showInactive()', () => { + it('should not focus on window', () => { + w.showInactive() + expect(w.isFocused()).to.equal(false) + }) + }) + + describe('BrowserWindow.focus()', () => { + it('does not make the window become visible', () => { + expect(w.isVisible()).to.equal(false) + w.focus() + expect(w.isVisible()).to.equal(false) + }) + }) + + describe('BrowserWindow.blur()', () => { + it('removes focus from window', () => { + w.blur() + expect(w.isFocused()).to.equal(false) + }) + }) + + describe('BrowserWindow.getFocusedWindow()', () => { + it('returns the opener window when dev tools window is focused', (done) => { + w.show() + w.webContents.once('devtools-focused', () => { + expect(BrowserWindow.getFocusedWindow()).to.equal(w) + done() + }) + w.webContents.openDevTools({ mode: 'undocked' }) + }) + }) + + describe('BrowserWindow.moveTop()', () => { + it('should not steal focus', async () => { + const posDelta = 50 + const wShownInactive = emittedOnce(w, 'show') + w.showInactive() + await wShownInactive + expect(w.isFocused()).to.equal(false) + + const otherWindow = new BrowserWindow({ show: false, title: 'otherWindow' }) + const otherWindowShown = emittedOnce(otherWindow, 'show') + otherWindow.show() + await otherWindowShown + expect(otherWindow.isFocused()).to.equal(true) + + w.moveTop() + const wPos = w.getPosition() + const wMoving = emittedOnce(w, 'move') + w.setPosition(wPos[0] + posDelta, wPos[1] + posDelta) + await wMoving + expect(w.isFocused()).to.equal(false) + expect(otherWindow.isFocused()).to.equal(true) + + const wFocused = emittedOnce(w, 'focus') + w.focus() + await wFocused + expect(w.isFocused()).to.equal(true) + + otherWindow.moveTop() + const otherWindowPos = otherWindow.getPosition() + const otherWindowMoving = emittedOnce(otherWindow, 'move') + otherWindow.setPosition(otherWindowPos[0] + posDelta, otherWindowPos[1] + posDelta) + await otherWindowMoving + expect(otherWindow.isFocused()).to.equal(false) + expect(w.isFocused()).to.equal(true) + + await closeWindow(otherWindow, { assertNotWindows: false }) + expect(BrowserWindow.getAllWindows()).to.have.lengthOf(1) + }) + }) + + }) + + describe('sizing', () => { + let w = null as unknown as BrowserWindow + beforeEach(() => { + w = new BrowserWindow({show: false, width: 400, height: 400}) + }) + afterEach(async () => { + await closeWindow(w) + w = null as unknown as BrowserWindow + }) + + describe('BrowserWindow.setBounds(bounds[, animate])', () => { + it('sets the window bounds with full bounds', () => { + const fullBounds = { x: 440, y: 225, width: 500, height: 400 } + w.setBounds(fullBounds) + + expectBoundsEqual(w.getBounds(), fullBounds) + }) + + it('sets the window bounds with partial bounds', () => { + const fullBounds = { x: 440, y: 225, width: 500, height: 400 } + w.setBounds(fullBounds) + + const boundsUpdate = { width: 200 } + w.setBounds(boundsUpdate as any) + + const expectedBounds = Object.assign(fullBounds, boundsUpdate) + expectBoundsEqual(w.getBounds(), expectedBounds) + }) + }) + + describe('BrowserWindow.setSize(width, height)', () => { + it('sets the window size', async () => { + const size = [300, 400] + + const resized = emittedOnce(w, 'resize') + w.setSize(size[0], size[1]) + await resized + + expectBoundsEqual(w.getSize(), size) + }) + }) + + describe('BrowserWindow.setMinimum/MaximumSize(width, height)', () => { + it('sets the maximum and minimum size of the window', () => { + expect(w.getMinimumSize()).to.deep.equal([0, 0]) + expect(w.getMaximumSize()).to.deep.equal([0, 0]) + + w.setMinimumSize(100, 100) + expectBoundsEqual(w.getMinimumSize(), [100, 100]) + expectBoundsEqual(w.getMaximumSize(), [0, 0]) + + w.setMaximumSize(900, 600) + expectBoundsEqual(w.getMinimumSize(), [100, 100]) + expectBoundsEqual(w.getMaximumSize(), [900, 600]) + }) + }) + + describe('BrowserWindow.setAspectRatio(ratio)', () => { + it('resets the behaviour when passing in 0', (done) => { + const size = [300, 400] + w.setAspectRatio(1 / 2) + w.setAspectRatio(0) + w.once('resize', () => { + expectBoundsEqual(w.getSize(), size) + done() + }) + w.setSize(size[0], size[1]) + }) + }) + + describe('BrowserWindow.setPosition(x, y)', () => { + it('sets the window position', (done) => { + const pos = [10, 10] + w.once('move', () => { + const newPos = w.getPosition() + expect(newPos).to.deep.equal(pos) + done() + }) + w.setPosition(pos[0], pos[1]) + }) + }) + + describe('BrowserWindow.setContentSize(width, height)', () => { + it('sets the content size', (done) => { + // NB. The CI server has a very small screen. Attempting to size the window + // larger than the screen will limit the window's size to the screen and + // cause the test to fail. + const size = [456, 567] + w.setContentSize(size[0], size[1]) + setImmediate(() => { + const after = w.getContentSize() + expect(after).to.deep.equal(size) + done() + }) + }) + it('works for a frameless window', (done) => { + w.destroy() + w = new BrowserWindow({ + show: false, + frame: false, + width: 400, + height: 400 + }) + const size = [456, 567] + w.setContentSize(size[0], size[1]) + setImmediate(() => { + const after = w.getContentSize() + expect(after).to.deep.equal(size) + done() + }) + }) + }) + + describe('BrowserWindow.setContentBounds(bounds)', () => { + it('sets the content size and position', (done) => { + const bounds = { x: 10, y: 10, width: 250, height: 250 } + w.once('resize', () => { + setTimeout(() => { + expectBoundsEqual(w.getContentBounds(), bounds) + done() + }) + }) + w.setContentBounds(bounds) + }) + it('works for a frameless window', (done) => { + w.destroy() + w = new BrowserWindow({ + show: false, + frame: false, + width: 300, + height: 300 + }) + const bounds = { x: 10, y: 10, width: 250, height: 250 } + w.once('resize', () => { + setTimeout(() => { + expect(w.getContentBounds()).to.deep.equal(bounds) + done() + }) + }) + w.setContentBounds(bounds) + }) + }) + + describe(`BrowserWindow.getNormalBounds()`, () => { + describe(`Normal state`, () => { + it(`checks normal bounds after resize`, (done) => { + const size = [300, 400] + w.once('resize', () => { + expectBoundsEqual(w.getNormalBounds(), w.getBounds()) + done() + }) + w.setSize(size[0], size[1]) + }) + it(`checks normal bounds after move`, (done) => { + const pos = [10, 10] + w.once('move', () => { + expectBoundsEqual(w.getNormalBounds(), w.getBounds()) + done() + }) + w.setPosition(pos[0], pos[1]) + }) + }) + ifdescribe(process.platform !== 'linux')(`Maximized state`, () => { + it(`checks normal bounds when maximized`, (done) => { + const bounds = w.getBounds() + w.once('maximize', () => { + expectBoundsEqual(w.getNormalBounds(), bounds) + done() + }) + w.show() + w.maximize() + }) + it(`checks normal bounds when unmaximized`, (done) => { + const bounds = w.getBounds() + w.once('maximize', () => { + w.unmaximize() + }) + w.once('unmaximize', () => { + expectBoundsEqual(w.getNormalBounds(), bounds) + done() + }) + w.show() + w.maximize() + }) + }) + ifdescribe(process.platform !== 'linux')(`Minimized state`, () => { + it(`checks normal bounds when minimized`, (done) => { + const bounds = w.getBounds() + w.once('minimize', () => { + expectBoundsEqual(w.getNormalBounds(), bounds) + done() + }) + w.show() + w.minimize() + }) + it(`checks normal bounds when restored`, (done) => { + const bounds = w.getBounds() + w.once('minimize', () => { + w.restore() + }) + w.once('restore', () => { + expectBoundsEqual(w.getNormalBounds(), bounds) + done() + }) + w.show() + w.minimize() + }) + }) + ifdescribe(process.platform === 'win32')(`Fullscreen state`, () => { + it(`checks normal bounds when fullscreen'ed`, (done) => { + const bounds = w.getBounds() + w.once('enter-full-screen', () => { + expectBoundsEqual(w.getNormalBounds(), bounds) + done() + }) + w.show() + w.setFullScreen(true) + }) + it(`checks normal bounds when unfullscreen'ed`, (done) => { + const bounds = w.getBounds() + w.once('enter-full-screen', () => { + w.setFullScreen(false) + }) + w.once('leave-full-screen', () => { + expectBoundsEqual(w.getNormalBounds(), bounds) + done() + }) + w.show() + w.setFullScreen(true) + }) }) - w.show() }) }) - describe('BrowserWindow.hide()', () => { + ifdescribe(process.platform === 'darwin')('tabbed windows', () => { let w = null as unknown as BrowserWindow beforeEach(() => { - w = new BrowserWindow({show: false, webPreferences: {nodeIntegration: true}}) + w = new BrowserWindow({show: false}) }) afterEach(async () => { await closeWindow(w) w = null as unknown as BrowserWindow }) - it('should defocus on window', () => { - w.hide() - expect(w.isFocused()).to.equal(false) + + describe('BrowserWindow.selectPreviousTab()', () => { + it('does not throw', () => { + expect(() => { + w.selectPreviousTab() + }).to.not.throw() + }) }) - it('should make the window not visible', () => { - w.show() - w.hide() - expect(w.isVisible()).to.equal(false) + + describe('BrowserWindow.selectNextTab()', () => { + it('does not throw', () => { + expect(() => { + w.selectNextTab() + }).to.not.throw() + }) }) - it('emits when window is hidden', async () => { - const shown = emittedOnce(w, 'show') + + describe('BrowserWindow.mergeAllWindows()', () => { + it('does not throw', () => { + expect(() => { + w.mergeAllWindows() + }).to.not.throw() + }) + }) + + describe('BrowserWindow.moveTabToNewWindow()', () => { + it('does not throw', () => { + expect(() => { + w.moveTabToNewWindow() + }).to.not.throw() + }) + }) + + describe('BrowserWindow.toggleTabBar()', () => { + it('does not throw', () => { + expect(() => { + w.toggleTabBar() + }).to.not.throw() + }) + }) + + describe('BrowserWindow.addTabbedWindow()', () => { + it('does not throw', async () => { + const tabbedWindow = new BrowserWindow({}) + expect(() => { + w.addTabbedWindow(tabbedWindow) + }).to.not.throw() + + expect(BrowserWindow.getAllWindows()).to.have.lengthOf(2) // w + tabbedWindow + + await closeWindow(tabbedWindow, { assertNotWindows: false }) + expect(BrowserWindow.getAllWindows()).to.have.lengthOf(1) // w + }) + + it('throws when called on itself', () => { + expect(() => { + w.addTabbedWindow(w) + }).to.throw('AddTabbedWindow cannot be called by a window on itself.') + }) + }) + }) + + describe('autoHideMenuBar property', () => { + afterEach(closeAllWindows) + it('exists', () => { + const w = new BrowserWindow({show: false}) + expect(w).to.have.property('autoHideMenuBar') + + // TODO(codebytere): remove when propertyification is complete + expect(w.setAutoHideMenuBar).to.be.a('function') + expect(w.isMenuBarAutoHide).to.be.a('function') + }) + }) + + describe('BrowserWindow.capturePage(rect)', () => { + afterEach(closeAllWindows) + + it('returns a Promise with a Buffer', async () => { + const w = new BrowserWindow({show: false}) + const image = await w.capturePage({ + x: 0, + y: 0, + width: 100, + height: 100 + }) + + expect(image.isEmpty()).to.equal(true) + }) + + it('preserves transparency', async () => { + const w = new BrowserWindow({show: false, transparent: true}) + w.loadURL('about:blank') + await emittedOnce(w, 'ready-to-show') w.show() - await shown - const hidden = emittedOnce(w, 'hide') - w.hide() - await hidden - expect(w.isVisible()).to.equal(false) + + const image = await w.capturePage() + const imgBuffer = image.toPNG() + + // Check the 25th byte in the PNG. + // Values can be 0,2,3,4, or 6. We want 6, which is RGB + Alpha + expect(imgBuffer[25]).to.equal(6) + }) + }) + + describe('BrowserWindow.setProgressBar(progress)', () => { + let w = null as unknown as BrowserWindow + before(() => { + w = new BrowserWindow({show: false}) + }) + after(async () => { + await closeWindow(w) + w = null as unknown as BrowserWindow + }) + it('sets the progress', () => { + expect(() => { + if (process.platform === 'darwin') { + app.dock.setIcon(path.join(fixtures, 'assets', 'logo.png')) + } + w.setProgressBar(0.5) + + if (process.platform === 'darwin') { + app.dock.setIcon(null as any) + } + w.setProgressBar(-1) + }).to.not.throw() + }) + it('sets the progress using "paused" mode', () => { + expect(() => { + w.setProgressBar(0.5, { mode: 'paused' }) + }).to.not.throw() + }) + it('sets the progress using "error" mode', () => { + expect(() => { + w.setProgressBar(0.5, { mode: 'error' }) + }).to.not.throw() + }) + it('sets the progress using "normal" mode', () => { + expect(() => { + w.setProgressBar(0.5, { mode: 'normal' }) + }).to.not.throw() + }) + }) + + describe('BrowserWindow.setAlwaysOnTop(flag, level)', () => { + let w = null as unknown as BrowserWindow + beforeEach(() => { + w = new BrowserWindow({show: false}) + }) + afterEach(async () => { + await closeWindow(w) + w = null as unknown as BrowserWindow + }) + + it('sets the window as always on top', () => { + expect(w.isAlwaysOnTop()).to.equal(false) + w.setAlwaysOnTop(true, 'screen-saver') + expect(w.isAlwaysOnTop()).to.equal(true) + w.setAlwaysOnTop(false) + expect(w.isAlwaysOnTop()).to.equal(false) + w.setAlwaysOnTop(true) + expect(w.isAlwaysOnTop()).to.equal(true) + }) + + ifit(process.platform === 'darwin')('raises an error when relativeLevel is out of bounds', () => { + expect(() => { + w.setAlwaysOnTop(true, 'normal', -2147483644) + }).to.throw() + + expect(() => { + w.setAlwaysOnTop(true, 'normal', 2147483632) + }).to.throw() + }) + + ifit(process.platform === 'darwin')('resets the windows level on minimize', () => { + expect(w.isAlwaysOnTop()).to.equal(false) + w.setAlwaysOnTop(true, 'screen-saver') + expect(w.isAlwaysOnTop()).to.equal(true) + w.minimize() + expect(w.isAlwaysOnTop()).to.equal(false) + w.restore() + expect(w.isAlwaysOnTop()).to.equal(true) }) }) diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index 98031bb11e51..e310090dc780 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -113,431 +113,6 @@ describe('BrowserWindow module', () => { afterEach(closeTheWindow) - describe('BrowserWindow.showInactive()', () => { - it('should not focus on window', () => { - w.showInactive() - expect(w.isFocused()).to.be.false() - }) - }) - - describe('BrowserWindow.focus()', () => { - it('does not make the window become visible', () => { - expect(w.isVisible()).to.be.false() - w.focus() - expect(w.isVisible()).to.be.false() - }) - }) - - describe('BrowserWindow.blur()', () => { - it('removes focus from window', () => { - w.blur() - expect(w.isFocused()).to.be.false() - }) - }) - - describe('BrowserWindow.getFocusedWindow()', () => { - it('returns the opener window when dev tools window is focused', (done) => { - w.show() - w.webContents.once('devtools-focused', () => { - expect(BrowserWindow.getFocusedWindow()).to.equal(w) - done() - }) - w.webContents.openDevTools({ mode: 'undocked' }) - }) - }) - - describe('BrowserWindow autoHideMenuBar property', () => { - it('has an autoHideMenuBar property', () => { - expect(w).to.have.a.property('autoHideMenuBar') - - // TODO(codebytere): remove when propertyification is complete - expect(w.setAutoHideMenuBar).to.be.a('function') - expect(w.isMenuBarAutoHide).to.be.a('function') - }) - }) - - describe('BrowserWindow.moveTop()', () => { - it('should not steal focus', async () => { - const posDelta = 50 - const wShownInactive = emittedOnce(w, 'show') - w.showInactive() - await wShownInactive - expect(w.isFocused()).to.be.false() - - const otherWindow = new BrowserWindow({ show: false, title: 'otherWindow' }) - const otherWindowShown = emittedOnce(otherWindow, 'show') - otherWindow.loadURL('data:text/html,') - otherWindow.show() - await otherWindowShown - expect(otherWindow.isFocused()).to.be.true() - - w.moveTop() - const wPos = w.getPosition() - const wMoving = emittedOnce(w, 'move') - w.setPosition(wPos[0] + posDelta, wPos[1] + posDelta) - await wMoving - expect(w.isFocused()).to.be.false() - expect(otherWindow.isFocused()).to.be.true() - - const wFocused = emittedOnce(w, 'focus') - w.focus() - await wFocused - expect(w.isFocused()).to.be.true() - - otherWindow.moveTop() - const otherWindowPos = otherWindow.getPosition() - const otherWindowMoving = emittedOnce(otherWindow, 'move') - otherWindow.setPosition(otherWindowPos[0] + posDelta, otherWindowPos[1] + posDelta) - await otherWindowMoving - expect(otherWindow.isFocused()).to.be.false() - expect(w.isFocused()).to.be.true() - - await closeWindow(otherWindow, { assertSingleWindow: false }).then(() => { - expect(BrowserWindow.getAllWindows()).to.have.lengthOf(2) // Test window + w - }) - }) - }) - - describe('BrowserWindow.capturePage(rect)', (done) => { - it('returns a Promise with a Buffer', async () => { - const image = await w.capturePage({ - x: 0, - y: 0, - width: 100, - height: 100 - }) - - expect(image.isEmpty()).to.be.true() - }) - - it('preserves transparency', async () => { - const w = await openTheWindow({ - show: false, - width: 400, - height: 400, - transparent: true - }) - const p = emittedOnce(w, 'ready-to-show') - w.loadURL('data:text/html,') - await p - w.show() - - const image = await w.capturePage() - const imgBuffer = image.toPNG() - - // Check the 25th byte in the PNG. - // Values can be 0,2,3,4, or 6. We want 6, which is RGB + Alpha - expect(imgBuffer[25]).to.equal(6) - }) - }) - - describe('BrowserWindow.setBounds(bounds[, animate])', () => { - it('sets the window bounds with full bounds', () => { - const fullBounds = { x: 440, y: 225, width: 500, height: 400 } - w.setBounds(fullBounds) - - expectBoundsEqual(w.getBounds(), fullBounds) - }) - - it('sets the window bounds with partial bounds', () => { - const fullBounds = { x: 440, y: 225, width: 500, height: 400 } - w.setBounds(fullBounds) - - const boundsUpdate = { width: 200 } - w.setBounds(boundsUpdate) - - const expectedBounds = Object.assign(fullBounds, boundsUpdate) - expectBoundsEqual(w.getBounds(), expectedBounds) - }) - }) - - describe('BrowserWindow.setSize(width, height)', () => { - it('sets the window size', async () => { - const size = [300, 400] - - const resized = emittedOnce(w, 'resize') - w.setSize(size[0], size[1]) - await resized - - expectBoundsEqual(w.getSize(), size) - }) - }) - - describe('BrowserWindow.setMinimum/MaximumSize(width, height)', () => { - it('sets the maximum and minimum size of the window', () => { - expect(w.getMinimumSize()).to.deep.equal([0, 0]) - expect(w.getMaximumSize()).to.deep.equal([0, 0]) - - w.setMinimumSize(100, 100) - expectBoundsEqual(w.getMinimumSize(), [100, 100]) - expectBoundsEqual(w.getMaximumSize(), [0, 0]) - - w.setMaximumSize(900, 600) - expectBoundsEqual(w.getMinimumSize(), [100, 100]) - expectBoundsEqual(w.getMaximumSize(), [900, 600]) - }) - }) - - describe('BrowserWindow.setAspectRatio(ratio)', () => { - it('resets the behaviour when passing in 0', (done) => { - const size = [300, 400] - w.setAspectRatio(1 / 2) - w.setAspectRatio(0) - w.once('resize', () => { - expectBoundsEqual(w.getSize(), size) - done() - }) - w.setSize(size[0], size[1]) - }) - }) - - describe('BrowserWindow.setPosition(x, y)', () => { - it('sets the window position', (done) => { - const pos = [10, 10] - w.once('move', () => { - const newPos = w.getPosition() - expect(newPos).to.deep.equal(pos) - done() - }) - w.setPosition(pos[0], pos[1]) - }) - }) - - describe('BrowserWindow.setContentSize(width, height)', () => { - it('sets the content size', () => { - const size = [400, 400] - w.setContentSize(size[0], size[1]) - const after = w.getContentSize() - expect(after).to.deep.equal(size) - }) - it('works for a frameless window', () => { - w.destroy() - w = new BrowserWindow({ - show: false, - frame: false, - width: 400, - height: 400 - }) - const size = [400, 400] - w.setContentSize(size[0], size[1]) - const after = w.getContentSize() - expect(after).to.deep.equal(size) - }) - }) - - describe('BrowserWindow.setContentBounds(bounds)', () => { - it('sets the content size and position', (done) => { - const bounds = { x: 10, y: 10, width: 250, height: 250 } - w.once('resize', () => { - expectBoundsEqual(w.getContentBounds(), bounds) - done() - }) - w.setContentBounds(bounds) - }) - it('works for a frameless window', (done) => { - w.destroy() - w = new BrowserWindow({ - show: false, - frame: false, - width: 300, - height: 300 - }) - const bounds = { x: 10, y: 10, width: 250, height: 250 } - w.once('resize', () => { - expect(w.getContentBounds()).to.deep.equal(bounds) - done() - }) - w.setContentBounds(bounds) - }) - }) - - describe(`BrowserWindow.getNormalBounds()`, () => { - describe(`Normal state`, () => { - it(`checks normal bounds after resize`, (done) => { - const size = [300, 400] - w.once('resize', () => { - expectBoundsEqual(w.getNormalBounds(), w.getBounds()) - done() - }) - w.setSize(size[0], size[1]) - }) - it(`checks normal bounds after move`, (done) => { - const pos = [10, 10] - w.once('move', () => { - expectBoundsEqual(w.getNormalBounds(), w.getBounds()) - done() - }) - w.setPosition(pos[0], pos[1]) - }) - }) - describe(`Maximized state`, () => { - before(function () { - if (isCI) { - this.skip() - } - }) - it(`checks normal bounds when maximized`, (done) => { - const bounds = w.getBounds() - w.once('maximize', () => { - expectBoundsEqual(w.getNormalBounds(), bounds) - done() - }) - w.show() - w.maximize() - }) - it(`checks normal bounds when unmaximized`, (done) => { - const bounds = w.getBounds() - w.once('maximize', () => { - w.unmaximize() - }) - w.once('unmaximize', () => { - expectBoundsEqual(w.getNormalBounds(), bounds) - done() - }) - w.show() - w.maximize() - }) - }) - describe(`Minimized state`, () => { - before(function () { - if (isCI) { - this.skip() - } - }) - it(`checks normal bounds when minimized`, (done) => { - const bounds = w.getBounds() - w.once('minimize', () => { - expectBoundsEqual(w.getNormalBounds(), bounds) - done() - }) - w.show() - w.minimize() - }) - it(`checks normal bounds when restored`, (done) => { - const bounds = w.getBounds() - w.once('minimize', () => { - w.restore() - }) - w.once('restore', () => { - expectBoundsEqual(w.getNormalBounds(), bounds) - done() - }) - w.show() - w.minimize() - }) - }) - describe(`Fullscreen state`, () => { - before(function () { - if (isCI) { - this.skip() - } - if (process.platform === 'darwin') { - this.skip() - } - }) - it(`checks normal bounds when fullscreen'ed`, (done) => { - const bounds = w.getBounds() - w.once('enter-full-screen', () => { - expectBoundsEqual(w.getNormalBounds(), bounds) - done() - }) - w.show() - w.setFullScreen(true) - }) - it(`checks normal bounds when unfullscreen'ed`, (done) => { - const bounds = w.getBounds() - w.once('enter-full-screen', () => { - w.setFullScreen(false) - }) - w.once('leave-full-screen', () => { - expectBoundsEqual(w.getNormalBounds(), bounds) - done() - }) - w.show() - w.setFullScreen(true) - }) - }) - }) - - describe('BrowserWindow.setProgressBar(progress)', () => { - it('sets the progress', () => { - expect(() => { - if (process.platform === 'darwin') { - app.dock.setIcon(path.join(fixtures, 'assets', 'logo.png')) - } - w.setProgressBar(0.5) - - if (process.platform === 'darwin') { - app.dock.setIcon(null) - } - w.setProgressBar(-1) - }).to.not.throw() - }) - it('sets the progress using "paused" mode', () => { - expect(() => { - w.setProgressBar(0.5, { mode: 'paused' }) - }).to.not.throw() - }) - it('sets the progress using "error" mode', () => { - expect(() => { - w.setProgressBar(0.5, { mode: 'error' }) - }).to.not.throw() - }) - it('sets the progress using "normal" mode', () => { - expect(() => { - w.setProgressBar(0.5, { mode: 'normal' }) - }).to.not.throw() - }) - }) - - describe('BrowserWindow.setAlwaysOnTop(flag, level)', () => { - it('sets the window as always on top', () => { - expect(w.isAlwaysOnTop()).to.be.false() - w.setAlwaysOnTop(true, 'screen-saver') - expect(w.isAlwaysOnTop()).to.be.true() - w.setAlwaysOnTop(false) - expect(w.isAlwaysOnTop()).to.be.false() - w.setAlwaysOnTop(true) - expect(w.isAlwaysOnTop()).to.be.true() - }) - it('raises an error when relativeLevel is out of bounds', function () { - if (process.platform !== 'darwin') { - // FIXME(alexeykuzmin): Skip the test instead of marking it as passed. - // afterEach hook won't be run if a test is skipped dynamically. - // If afterEach isn't run current window won't be destroyed - // and the next test will fail on assertion in `closeWindow()`. - // this.skip() - return - } - - expect(() => { - w.setAlwaysOnTop(true, '', -2147483644) - }).to.throw() - - expect(() => { - w.setAlwaysOnTop(true, '', 2147483632) - }).to.throw() - }) - }) - - describe('BrowserWindow.alwaysOnTop() resets level on minimize', () => { - before(function () { - if (process.platform !== 'darwin') { - this.skip() - } - }) - - it('resets the windows level on minimize', () => { - expect(w.isAlwaysOnTop()).to.be.false() - w.setAlwaysOnTop(true, 'screen-saver') - expect(w.isAlwaysOnTop()).to.be.true() - w.minimize() - expect(w.isAlwaysOnTop()).to.be.false() - w.restore() - expect(w.isAlwaysOnTop()).to.be.true() - }) - }) - describe('BrowserWindow.setAutoHideCursor(autoHide)', () => { describe('on macOS', () => { before(function () { @@ -567,104 +142,6 @@ describe('BrowserWindow module', () => { }) }) - describe('BrowserWindow.selectPreviousTab()', () => { - before(function () { - if (process.platform !== 'darwin') { - this.skip() - } - }) - - it('does not throw', () => { - expect(() => { - w.selectPreviousTab() - }).to.not.throw() - }) - }) - - describe('BrowserWindow.selectNextTab()', () => { - before(function () { - if (process.platform !== 'darwin') { - this.skip() - } - }) - - it('does not throw', () => { - expect(() => { - w.selectNextTab() - }).to.not.throw() - }) - }) - - describe('BrowserWindow.mergeAllWindows()', () => { - before(function () { - if (process.platform !== 'darwin') { - this.skip() - } - }) - - it('does not throw', () => { - expect(() => { - w.mergeAllWindows() - }).to.not.throw() - }) - }) - - describe('BrowserWindow.moveTabToNewWindow()', () => { - before(function () { - if (process.platform !== 'darwin') { - this.skip() - } - }) - - it('does not throw', () => { - expect(() => { - w.moveTabToNewWindow() - }).to.not.throw() - }) - }) - - describe('BrowserWindow.toggleTabBar()', () => { - before(function () { - if (process.platform !== 'darwin') { - this.skip() - } - }) - - it('does not throw', () => { - expect(() => { - w.toggleTabBar() - }).to.not.throw() - }) - }) - - describe('BrowserWindow.addTabbedWindow()', () => { - before(function () { - if (process.platform !== 'darwin') { - this.skip() - } - }) - - it('does not throw', (done) => { - const tabbedWindow = new BrowserWindow({}) - expect(() => { - w.addTabbedWindow(tabbedWindow) - }).to.not.throw() - - expect(BrowserWindow.getAllWindows()).to.have.lengthOf(3) // Test window + w + tabbedWindow - - closeWindow(tabbedWindow, { assertSingleWindow: false }).then(() => { - expect(BrowserWindow.getAllWindows()).to.have.lengthOf(2) // Test window + w - done() - }) - }) - - it('throws when called on itself', () => { - expect(() => { - w.addTabbedWindow(w) - }).to.throw('AddTabbedWindow cannot be called by a window on itself.') - }) - }) - describe('BrowserWindow.setWindowButtonVisibility()', () => { before(function () { if (process.platform !== 'darwin') {