Improve window activity detection, improving notification delivery
This commit is contained in:
parent
be9721c72d
commit
8ace4b6321
7 changed files with 290 additions and 46 deletions
164
ts/test-electron/services/ActiveWindowService_test.ts
Normal file
164
ts/test-electron/services/ActiveWindowService_test.ts
Normal file
|
@ -0,0 +1,164 @@
|
|||
// Copyright 2020 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { assert } from 'chai';
|
||||
import * as sinon from 'sinon';
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
import { ActiveWindowService } from '../../services/ActiveWindowService';
|
||||
|
||||
describe('ActiveWindowService', () => {
|
||||
const fakeIpcEvent = {};
|
||||
|
||||
beforeEach(function beforeEach() {
|
||||
this.clock = sinon.useFakeTimers({ now: 1000 });
|
||||
});
|
||||
|
||||
afterEach(function afterEach() {
|
||||
this.clock.restore();
|
||||
});
|
||||
|
||||
function createFakeDocument() {
|
||||
return document.createElement('div');
|
||||
}
|
||||
|
||||
it('is inactive at the start', () => {
|
||||
const service = new ActiveWindowService();
|
||||
service.initialize(createFakeDocument(), new EventEmitter());
|
||||
|
||||
assert.isFalse(service.isActive());
|
||||
});
|
||||
|
||||
it('becomes active after focusing', () => {
|
||||
const fakeIpc = new EventEmitter();
|
||||
const service = new ActiveWindowService();
|
||||
service.initialize(createFakeDocument(), fakeIpc);
|
||||
|
||||
fakeIpc.emit('set-window-focus', fakeIpcEvent, true);
|
||||
|
||||
assert.isTrue(service.isActive());
|
||||
});
|
||||
|
||||
it('becomes inactive after 15 seconds without interaction', function test() {
|
||||
const fakeIpc = new EventEmitter();
|
||||
const service = new ActiveWindowService();
|
||||
service.initialize(createFakeDocument(), fakeIpc);
|
||||
|
||||
fakeIpc.emit('set-window-focus', fakeIpcEvent, true);
|
||||
|
||||
this.clock.tick(5000);
|
||||
assert.isTrue(service.isActive());
|
||||
|
||||
this.clock.tick(9999);
|
||||
assert.isTrue(service.isActive());
|
||||
|
||||
this.clock.tick(1);
|
||||
assert.isFalse(service.isActive());
|
||||
});
|
||||
|
||||
['click', 'keydown', 'mousedown', 'mousemove', 'touchstart', 'wheel'].forEach(
|
||||
(eventName: string) => {
|
||||
it(`is inactive even in the face of ${eventName} events if unfocused`, function test() {
|
||||
const fakeDocument = createFakeDocument();
|
||||
const fakeIpc = new EventEmitter();
|
||||
const service = new ActiveWindowService();
|
||||
service.initialize(fakeDocument, fakeIpc);
|
||||
|
||||
fakeIpc.emit('set-window-focus', fakeIpcEvent, false);
|
||||
|
||||
fakeDocument.dispatchEvent(new Event(eventName));
|
||||
assert.isFalse(service.isActive());
|
||||
});
|
||||
|
||||
it(`stays active if focused and receiving ${eventName} events`, function test() {
|
||||
const fakeDocument = createFakeDocument();
|
||||
const fakeIpc = new EventEmitter();
|
||||
const service = new ActiveWindowService();
|
||||
service.initialize(fakeDocument, fakeIpc);
|
||||
|
||||
fakeIpc.emit('set-window-focus', fakeIpcEvent, true);
|
||||
|
||||
fakeDocument.dispatchEvent(new Event(eventName));
|
||||
assert.isTrue(service.isActive());
|
||||
|
||||
this.clock.tick(8000);
|
||||
fakeDocument.dispatchEvent(new Event(eventName));
|
||||
assert.isTrue(service.isActive());
|
||||
|
||||
this.clock.tick(8000);
|
||||
fakeDocument.dispatchEvent(new Event(eventName));
|
||||
assert.isTrue(service.isActive());
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
it('calls callbacks when going from unfocused to focused', () => {
|
||||
const fakeIpc = new EventEmitter();
|
||||
const service = new ActiveWindowService();
|
||||
service.initialize(createFakeDocument(), fakeIpc);
|
||||
|
||||
const callback = sinon.stub();
|
||||
service.registerForActive(callback);
|
||||
|
||||
fakeIpc.emit('set-window-focus', fakeIpcEvent, true);
|
||||
|
||||
sinon.assert.calledOnce(callback);
|
||||
});
|
||||
|
||||
it('calls callbacks when receiving a click event after being focused', function test() {
|
||||
const fakeDocument = createFakeDocument();
|
||||
const fakeIpc = new EventEmitter();
|
||||
const service = new ActiveWindowService();
|
||||
service.initialize(fakeDocument, fakeIpc);
|
||||
|
||||
fakeIpc.emit('set-window-focus', fakeIpcEvent, true);
|
||||
|
||||
this.clock.tick(20000);
|
||||
|
||||
const callback = sinon.stub();
|
||||
service.registerForActive(callback);
|
||||
|
||||
fakeDocument.dispatchEvent(new Event('click'));
|
||||
|
||||
sinon.assert.calledOnce(callback);
|
||||
});
|
||||
|
||||
it('only calls callbacks every 5 seconds; it is throttled', function test() {
|
||||
const fakeIpc = new EventEmitter();
|
||||
const service = new ActiveWindowService();
|
||||
service.initialize(createFakeDocument(), fakeIpc);
|
||||
|
||||
const callback = sinon.stub();
|
||||
service.registerForActive(callback);
|
||||
|
||||
fakeIpc.emit('set-window-focus', fakeIpcEvent, true);
|
||||
fakeIpc.emit('set-window-focus', fakeIpcEvent, false);
|
||||
fakeIpc.emit('set-window-focus', fakeIpcEvent, true);
|
||||
fakeIpc.emit('set-window-focus', fakeIpcEvent, false);
|
||||
fakeIpc.emit('set-window-focus', fakeIpcEvent, true);
|
||||
fakeIpc.emit('set-window-focus', fakeIpcEvent, false);
|
||||
|
||||
sinon.assert.calledOnce(callback);
|
||||
|
||||
this.clock.tick(15000);
|
||||
|
||||
fakeIpc.emit('set-window-focus', fakeIpcEvent, true);
|
||||
|
||||
sinon.assert.calledTwice(callback);
|
||||
});
|
||||
|
||||
it('can remove callbacks', () => {
|
||||
const fakeDocument = createFakeDocument();
|
||||
const fakeIpc = new EventEmitter();
|
||||
const service = new ActiveWindowService();
|
||||
service.initialize(fakeDocument, fakeIpc);
|
||||
|
||||
const callback = sinon.stub();
|
||||
service.registerForActive(callback);
|
||||
service.unregisterForActive(callback);
|
||||
|
||||
fakeIpc.emit('set-window-focus', fakeIpcEvent, true);
|
||||
|
||||
sinon.assert.notCalled(callback);
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue