Skip to content

Commit 03851f5

Browse files
committed
test: mock navigator.locks and fix existing tests
1 parent b63bfe6 commit 03851f5

File tree

4 files changed

+66
-3
lines changed

4 files changed

+66
-3
lines changed

tests/mocks/state.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { objectDifference } from '../utils';
1717
export class StateMock {
1818
public acceleratorsToBlock: BlockableAccelerator[] = [];
1919
public activeGistAction = GistActionState.none;
20+
public activeVersions = new Set<string>();
2021
public channelsToShow: ElectronReleaseChannel[] = [];
2122
public editorMosaic = new EditorMosaic();
2223
public environmentVariables: string[] = [];
@@ -85,6 +86,7 @@ export class StateMock {
8586
public setVersion = jest.fn().mockImplementation((version: string) => {
8687
this.currentElectronVersion = this.versions[version];
8788
this.version = version;
89+
this.activeVersions.add(version);
8890
});
8991
public isVersionUsable = jest.fn().mockImplementation(() => {
9092
return { ver: this.currentElectronVersion };
@@ -120,6 +122,7 @@ export class StateMock {
120122
makeObservable(this, {
121123
acceleratorsToBlock: observable,
122124
activeGistAction: observable,
125+
activeVersions: observable,
123126
channelsToShow: observable,
124127
editorMosaic: observable,
125128
environmentVariables: observable,

tests/renderer/components/settings-electron-spec.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,21 @@ import { ElectronSettings } from '../../../src/renderer/components/settings-elec
1313
import { AppState } from '../../../src/renderer/state';
1414
import { disableDownload } from '../../../src/renderer/utils/disable-download';
1515
import { AppMock, StateMock, VersionsMock } from '../../mocks/mocks';
16+
import { waitFor } from '../../utils';
1617

1718
jest.mock('../../../src/renderer/utils/disable-download.ts');
1819

1920
describe('ElectronSettings component', () => {
2021
let store: StateMock;
2122
let mockVersions: Record<string, RunnableVersion>;
2223
let mockVersionsArray: RunnableVersion[];
24+
const version = '2.0.1';
2325

2426
beforeEach(() => {
2527
({ mockVersions, mockVersionsArray } = new VersionsMock());
2628
({ state: store } = window.ElectronFiddle.app as unknown as AppMock);
2729

28-
store.initVersions('2.0.1', { ...mockVersions });
30+
store.initVersions(version, { ...mockVersions });
2931
store.channelsToShow = [
3032
ElectronReleaseChannel.stable,
3133
ElectronReleaseChannel.beta,
@@ -39,7 +41,7 @@ describe('ElectronSettings component', () => {
3941
store.versionsToShow[i++].state = InstallState.installing;
4042
});
4143

42-
it('renders', () => {
44+
it('renders', async () => {
4345
const spy = jest
4446
.spyOn(window.ElectronFiddle, 'getOldestSupportedMajor')
4547
.mockReturnValue(9);
@@ -65,6 +67,10 @@ describe('ElectronSettings component', () => {
6567
const wrapper = shallow(
6668
<ElectronSettings appState={store as unknown as AppState} />,
6769
);
70+
71+
await store.setVersion(version);
72+
await waitFor(() => store.activeVersions.size > 0);
73+
6874
expect(wrapper).toMatchSnapshot();
6975

7076
spy.mockRestore();

tests/renderer/state-spec.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ import {
2121
saveLocalVersions,
2222
} from '../../src/renderer/versions';
2323
import { VersionsMock, createEditorValues } from '../mocks/mocks';
24-
import { overrideRendererPlatform, resetRendererPlatform } from '../utils';
24+
import {
25+
overrideRendererPlatform,
26+
resetRendererPlatform,
27+
waitFor,
28+
} from '../utils';
2529

2630
jest.mock('../../src/renderer/versions', () => {
2731
const { getReleaseChannel } = jest.requireActual(
@@ -311,6 +315,10 @@ describe('AppState', () => {
311315

312316
it('does not remove the active version', async () => {
313317
const ver = appState.versions[active];
318+
319+
await appState.setVersion(ver.version);
320+
await waitFor(() => appState.activeVersions.size > 0);
321+
314322
broadcastMessageSpy.mockClear();
315323
await appState.removeVersion(ver);
316324
expect(removeSpy).not.toHaveBeenCalled();

tests/setup.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,52 @@ delete (window as any).localStorage;
7676
window.navigator = window.navigator ?? {};
7777
(window.navigator.clipboard as any) = {};
7878

79+
class FakeNavigatorLocks implements LockManager {
80+
locks = {
81+
held: new Set<Lock>(),
82+
pending: new Set<Lock>(),
83+
};
84+
85+
query = async () => {
86+
const result = {
87+
held: [...this.locks.held],
88+
pending: [...this.locks.pending],
89+
};
90+
91+
return result as LockManagerSnapshot;
92+
};
93+
94+
/**
95+
* WIP. Right now, this is a **very** naive mock that will just happily grant a shared lock when one is requested,
96+
* but I'll add some bookkeeping and expand it to cover the exclusive lock case as well.
97+
*
98+
* @TODO remove this comment
99+
*/
100+
request = (async (...args: Parameters<LockManager['request']>) => {
101+
const [
102+
name,
103+
options = {
104+
mode: 'exclusive',
105+
},
106+
cb,
107+
] = args;
108+
109+
const { mode } = options;
110+
111+
const lock = { name, mode, cb } as Lock;
112+
113+
if (mode === 'shared') {
114+
this.locks.held.add(lock);
115+
116+
await cb(lock);
117+
118+
return;
119+
}
120+
}) as LockManager['request'];
121+
}
122+
123+
(window.navigator.locks as any) = new FakeNavigatorLocks();
124+
79125
/**
80126
* Mock these properties twice so that they're available
81127
* both at the top-level of files and also within the

0 commit comments

Comments
 (0)