Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minimizing new window flickering while painting #1134

Merged
merged 4 commits into from
Feb 8, 2025
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
3 changes: 3 additions & 0 deletions __mocks__/jquery.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ window.matchMedia = window.matchMedia || function()
removeListener: function() {}
};
};

// Mocking requestAnimationFrame since it's not usually defined but we use it
global.requestAnimationFrame = callback => callback();
42 changes: 25 additions & 17 deletions __tests__/__main__/main-window.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,21 @@ describe('main-window.mjs', () =>
assert.strictEqual(getLeaveByInterval(), null);
});

it('Should get window', () =>
it('Should get window', (done) =>
{
createWindow();
assert.strictEqual(showSpy.calledOnce, true);
assert.strictEqual(getMainWindow() instanceof BrowserWindow, true);
getMainWindow().webContents.ipc.on(IpcConstants.WindowReadyToShow, () =>
{
assert.strictEqual(showSpy.calledOnce, true);
done();
});
});
});

describe('createWindow()', () =>
{
it('Should create and get window default behaviour', () =>
it('Should create and get window default behaviour', (done) =>
{
const loadFileSpy = spy(BrowserWindow.prototype, 'loadFile');
createWindow();
Expand All @@ -73,9 +77,13 @@ describe('main-window.mjs', () =>
assert.strictEqual(mainWindow.listenerCount('minimize'), 2);
assert.strictEqual(mainWindow.listenerCount('close'), 2);
assert.strictEqual(loadFileSpy.calledOnce, true);
assert.strictEqual(showSpy.calledOnce, true);
assert.notStrictEqual(getLeaveByInterval(), null);
assert.strictEqual(getLeaveByInterval()._idleNext.expiry > 0, true);
mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, () =>
{
assert.strictEqual(showSpy.calledOnce, true);
done();
});
});
});

Expand All @@ -88,7 +96,7 @@ describe('main-window.mjs', () =>
* @type {BrowserWindow}
*/
const mainWindow = getMainWindow();
mainWindow.on('ready-to-show', async() =>
mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, async() =>
{
// Wait a bit for values to accomodate
await new Promise(res => setTimeout(res, 500));
Expand All @@ -114,7 +122,7 @@ describe('main-window.mjs', () =>
* @type {BrowserWindow}
*/
const mainWindow = getMainWindow();
mainWindow.on('ready-to-show', async() =>
mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, async() =>
{
// Wait a bit for values to accomodate
await new Promise(res => setTimeout(res, 500));
Expand Down Expand Up @@ -144,7 +152,7 @@ describe('main-window.mjs', () =>
* @type {BrowserWindow}
*/
const mainWindow = getMainWindow();
mainWindow.on('ready-to-show', async() =>
mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, async() =>
{
// Wait a bit for values to accomodate
await new Promise(res => setTimeout(res, 500));
Expand All @@ -170,7 +178,7 @@ describe('main-window.mjs', () =>
* @type {BrowserWindow}
*/
const mainWindow = getMainWindow();
mainWindow.on('ready-to-show', () =>
mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, () =>
{
stub(Notification, 'createLeaveNotification').callsFake(() =>
{
Expand Down Expand Up @@ -200,7 +208,7 @@ describe('main-window.mjs', () =>
* @type {BrowserWindow}
*/
const mainWindow = getMainWindow();
mainWindow.on('ready-to-show', () =>
mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, () =>
{
const now = new Date();
ipcMain.emit(
Expand All @@ -223,7 +231,7 @@ describe('main-window.mjs', () =>
* @type {BrowserWindow}
*/
const mainWindow = getMainWindow();
mainWindow.on('ready-to-show', () =>
mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, () =>
{
showSpy.callsFake(() =>
{
Expand All @@ -245,7 +253,7 @@ describe('main-window.mjs', () =>
* @type {BrowserWindow}
*/
const mainWindow = getMainWindow();
mainWindow.on('ready-to-show', () =>
mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, () =>
{
const trayStub = stub(global.tray, 'popUpContextMenu').callsFake(() =>
{
Expand All @@ -272,7 +280,7 @@ describe('main-window.mjs', () =>
* @type {BrowserWindow}
*/
const mainWindow = getMainWindow();
mainWindow.on('ready-to-show', () =>
mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, () =>
{
mainWindow.emit('minimize', {
preventDefault: () => {}
Expand All @@ -295,7 +303,7 @@ describe('main-window.mjs', () =>
*/
const mainWindow = getMainWindow();
const minimizeSpy = spy(mainWindow, 'minimize');
mainWindow.on('ready-to-show', () =>
mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, () =>
{
mainWindow.emit('minimize', {});
assert.strictEqual(minimizeSpy.called, true);
Expand All @@ -318,7 +326,7 @@ describe('main-window.mjs', () =>
* @type {BrowserWindow}
*/
const mainWindow = getMainWindow();
mainWindow.on('ready-to-show', () =>
mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, () =>
{
mainWindow.emit('close', {
preventDefault: () => {}
Expand All @@ -341,7 +349,7 @@ describe('main-window.mjs', () =>
* @type {BrowserWindow}
*/
const mainWindow = getMainWindow();
mainWindow.on('ready-to-show', () =>
mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, () =>
{
// Force the exit
mainWindow.on('close', () =>
Expand Down Expand Up @@ -396,7 +404,7 @@ describe('main-window.mjs', () =>
* @type {BrowserWindow}
*/
const mainWindow = getMainWindow();
mainWindow.on('ready-to-show', () =>
mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, () =>
{
mainWindow.emit('close', {
preventDefault: () => {}
Expand All @@ -422,7 +430,7 @@ describe('main-window.mjs', () =>
clock.restore();
done();
});
mainWindow.on('ready-to-show', () =>
mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, () =>
{
mainWindow.emit('close', {
preventDefault: () => {}
Expand Down
174 changes: 153 additions & 21 deletions __tests__/__main__/windows.mjs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
'use strict';

import assert from 'assert';
import { BrowserWindow } from 'electron';
import { stub } from 'sinon';
import { BrowserWindow, ipcMain } from 'electron';
import { spy, stub } from 'sinon';

import { getDateStr } from '../../js/date-aux.mjs';
import IpcConstants from '../../js/ipc-constants.mjs';
import Windows from '../../js/windows.mjs';

describe('Windows tests', () =>
Expand All @@ -14,17 +15,44 @@ describe('Windows tests', () =>
before(() =>
{
// Avoid window being shown
// TODO: might not always be working?
showSpy = stub(BrowserWindow.prototype, 'show');
loadSpy = stub(BrowserWindow.prototype, 'loadURL');
loadSpy = spy(BrowserWindow.prototype, 'loadURL');

// Mocking for tests below
ipcMain.handle(IpcConstants.GetWaiverDay, () =>
{
return new Promise((resolve) =>
{
resolve(global.waiverDay);
});
});
ipcMain.removeHandler(IpcConstants.GetLanguageData);
ipcMain.handle(IpcConstants.GetLanguageData, () => ({
'language': 'en',
'data': {
'translation': {
'$Preferences': {
'hideNonWorkingDay': ''
}
}
}
}));
ipcMain.handle(IpcConstants.GetWaiverStoreContents, () =>
{
return new Promise(resolve => resolve({}));
});
ipcMain.handle(IpcConstants.GetCountries, () =>
{
return new Promise(resolve => resolve([]));
});
});

it('Elements should be null on starting', () =>
{
assert.strictEqual(Windows.getWaiverWindow(), null);
assert.strictEqual(global.tray, null);
assert.strictEqual(global.contextMenu, null);
assert.strictEqual(global.prefWindow, null);
assert.strictEqual(Windows.getPreferencesWindow(), null);
});

it('Should create waiver window', (done) =>
Expand All @@ -41,24 +69,41 @@ describe('Windows tests', () =>
assert.strictEqual(Math.abs(size[0] - 600) < 10, true);
assert.strictEqual(Math.abs(size[1] - 500) < 10, true);

assert.strictEqual(showSpy.calledOnce, true);
assert.strictEqual(loadSpy.calledOnce, true);

done();
Windows.getWaiverWindow().webContents.ipc.on(IpcConstants.WindowReadyToShow, () =>
{
assert.strictEqual(showSpy.calledOnce, true);
done();
});
});

it('Should show waiver window it has been created', (done) =>
it('Should show waiver window when it has been created', (done) =>
{
const mainWindow = new BrowserWindow({
show: false
});
let firstShow = true;
showSpy.callsFake(() =>
{
if (firstShow)
{
firstShow = false;
Windows.openWaiverManagerWindow(mainWindow);
}
else
{
assert.notStrictEqual(Windows.getWaiverWindow(), null);

// It should only load once the URL because it already exists
assert.strictEqual(loadSpy.calledOnce, true);
assert.strictEqual(showSpy.calledTwice, true);
showSpy.restore();
showSpy = stub(BrowserWindow.prototype, 'show');
done();
}
});
Windows.openWaiverManagerWindow(mainWindow);
Windows.openWaiverManagerWindow(mainWindow);
assert.notStrictEqual(Windows.getWaiverWindow(), null);
// It should only load once the URL because it already exists
assert.strictEqual(showSpy.calledTwice, true);
assert.strictEqual(loadSpy.calledOnce, true);
done();
});

it('Should set global waiverDay when event is sent', (done) =>
Expand All @@ -67,19 +112,101 @@ describe('Windows tests', () =>
show: false
});
Windows.openWaiverManagerWindow(mainWindow, true);
assert.notStrictEqual(Windows.getWaiverWindow(), null);
assert.strictEqual(global.waiverDay, getDateStr(new Date()));
done();
Windows.getWaiverWindow().webContents.ipc.on(IpcConstants.WindowReadyToShow, () =>
{
assert.strictEqual(showSpy.calledOnce, true);
assert.notStrictEqual(Windows.getWaiverWindow(), null);
assert.strictEqual(global.waiverDay, getDateStr(new Date()));
done();
});
});

it('Should reset waiverWindow on close', () =>
it('Should reset waiverWindow on close', (done) =>
{
const mainWindow = new BrowserWindow({
show: false
});
Windows.openWaiverManagerWindow(mainWindow, true);
Windows.getWaiverWindow().close();
assert.strictEqual(Windows.getWaiverWindow(), null);
Windows.getWaiverWindow().webContents.ipc.on(IpcConstants.WindowReadyToShow, () =>
{
assert.strictEqual(showSpy.calledOnce, true);
Windows.getWaiverWindow().close();
assert.strictEqual(Windows.getWaiverWindow(), null);
done();
});
});

it('Should create preferences window', function(done)
{
// For some reason this test takes longer in the CI for windows-latest.
// The last requestAnimationFrame() call inside preferences.js has been taking ~2s.
this.timeout(5000);

const mainWindow = new BrowserWindow({
show: false
});

showSpy.callsFake(() =>
{
assert.notStrictEqual(Windows.getPreferencesWindow(), null);
assert.strictEqual(Windows.getPreferencesWindow() instanceof BrowserWindow, true);

// Values can vary about 10px from 600, 500
const size = Windows.getPreferencesWindow().getSize();
assert.strictEqual(Math.abs(size[0] - 550) < 10, true);
assert.strictEqual(Math.abs(size[1] - 620) < 10, true);

assert.strictEqual(loadSpy.calledOnce, true);

showSpy.restore();
showSpy = stub(BrowserWindow.prototype, 'show');
done();
});

Windows.openPreferencesWindow(mainWindow);
});

it('Should show preferences window when it has been created', (done) =>
{
const mainWindow = new BrowserWindow({
show: false
});
let firstShow = true;
showSpy.callsFake(() =>
{
if (firstShow)
{
firstShow = false;
Windows.openPreferencesWindow(mainWindow);
}
else
{
assert.notStrictEqual(Windows.getPreferencesWindow(), null);

// It should only load once the URL because it already exists
assert.strictEqual(loadSpy.calledOnce, true);
assert.strictEqual(showSpy.calledTwice, true);
showSpy.restore();
showSpy = stub(BrowserWindow.prototype, 'show');
done();
}
});
Windows.openPreferencesWindow(mainWindow);
});

it('Should reset preferences window on close', (done) =>
{
const mainWindow = new BrowserWindow({
show: false
});
Windows.openPreferencesWindow(mainWindow, true);
Windows.getPreferencesWindow().webContents.ipc.on(IpcConstants.WindowReadyToShow, () =>
{
assert.strictEqual(showSpy.calledOnce, true);
Windows.getPreferencesWindow().close();
assert.strictEqual(Windows.getPreferencesWindow(), null);
done();
});
});

it('Should get dialog coordinates', () =>
Expand Down Expand Up @@ -109,5 +236,10 @@ describe('Windows tests', () =>
{
showSpy.restore();
loadSpy.restore();

ipcMain.removeHandler(IpcConstants.GetWaiverDay);
ipcMain.removeHandler(IpcConstants.GetLanguageData);
ipcMain.removeHandler(IpcConstants.GetWaiverStoreContents);
ipcMain.removeHandler(IpcConstants.GetCountries);
});
});
});
Loading