Skip to content

Commit 1b04eeb

Browse files
authored
Upgrade Electron to v25 to related deps (#772)
* Initial work of upgrade electron to v25 * Fix devtools injection * Fix about menu * Remove devtools-installer setup * Move context-menu setup to main process * Remove devtron * Use fs.watchFile * Fix url-handle ip listen * Fix dialog * Migrate from spectron to playwright * Update CI * Remove spectron * CI: Use node 16 * Remove electron-rebuild & update script * Use patch-package for patch react-dev-utils * Add --no-notarize arg for easy build mac app on local * Bump electron-packager & related deps * Update CD * Move playwright-core to dev deps * Update docs/contributing.md * CI: Use windows-2022 * CI/CD: Increase network-timeout for windows * Fix app notariztion * E2E: Use wait-for-expect * Update window options * CI: Cancel previously in-progress run
1 parent 3b85aac commit 1b04eeb

29 files changed

+773
-1631
lines changed

.github/workflows/main.yml

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,48 +2,52 @@ name: CI
22

33
on: [push, pull_request]
44

5+
concurrency:
6+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
7+
cancel-in-progress: true
8+
59
jobs:
6-
build-test-macos:
7-
runs-on: macOS-latest
10+
build-test-linux:
11+
runs-on: ubuntu-latest
812
steps:
913
- uses: actions/checkout@v1
1014
- uses: actions/setup-node@v1
1115
with:
12-
node-version: 10.x
13-
- name: CI
16+
node-version: 16.x
17+
- name: Setup
18+
run: sudo apt-get install -y libgbm-dev
19+
- name: Test
1420
run: |
1521
yarn
1622
cd npm-package && yarn && cd ..
1723
yarn test
1824
yarn build
19-
yarn test-e2e
20-
build-test-linux:
21-
runs-on: ubuntu-latest
25+
xvfb-run --auto-servernum yarn test-e2e
26+
build-test-macos:
27+
runs-on: macOS-latest
2228
steps:
2329
- uses: actions/checkout@v1
2430
- uses: actions/setup-node@v1
2531
with:
26-
node-version: 10.x
27-
- name: CI
32+
node-version: 16.x
33+
- name: Test
2834
run: |
29-
export DISPLAY=:99.0
30-
Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
31-
npm i -g xvfb-maybe
3235
yarn
3336
cd npm-package && yarn && cd ..
3437
yarn test
3538
yarn build
36-
xvfb-maybe yarn test-e2e
39+
yarn test-e2e
3740
build-test-windows:
38-
runs-on: windows-2019
41+
runs-on: windows-2022
3942
steps:
4043
- uses: actions/checkout@v1
4144
- uses: actions/setup-node@v1
4245
with:
43-
node-version: 10.x
44-
- name: CI
46+
node-version: 16.x
47+
- name: Test
4548
shell: bash
4649
run: |
50+
yarn config set network-timeout 500000 -g
4751
yarn
4852
cd npm-package && yarn && cd ..
4953
yarn build

.github/workflows/release.yml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ on: release
44

55
jobs:
66
release-linux:
7-
runs-on: ubuntu-18.04
7+
runs-on: ubuntu-latest
88
steps:
99
- uses: actions/checkout@v1
1010
- uses: actions/setup-node@v1
1111
with:
12-
node-version: 10.x
12+
node-version: 16.x
1313
- name: Package
1414
run: |
1515
yarn
@@ -22,15 +22,16 @@ jobs:
2222
pattern: release/react-native-debugger*
2323
github-token: ${{ secrets.GITHUB_TOKEN }}
2424
release-windows:
25-
runs-on: windows-2019
25+
runs-on: windows-2022
2626
steps:
2727
- uses: actions/checkout@v1
2828
- uses: actions/setup-node@v1
2929
with:
30-
node-version: 10.x
30+
node-version: 16.x
3131
- name: Package
3232
shell: bash
3333
run: |
34+
yarn config set network-timeout 500000 -g
3435
yarn
3536
yarn build
3637
yarn pack-windows

__e2e__/app.spec.js

Lines changed: 46 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -2,62 +2,42 @@ import fs from 'fs';
22
import path from 'path';
33
import net from 'net';
44
import http from 'http';
5-
import electronPath from 'electron';
6-
import { Application } from 'spectron';
5+
import executablePath from 'electron';
6+
import { _electron as electron } from 'playwright-core';
7+
import waitForExpect from 'wait-for-expect';
78
import buildTestBundle, { bundlePath } from './buildTestBundle';
89
import createMockRNServer from './mockRNServer';
9-
import autoUpdateFeed from '../auto_update.json';
1010

1111
const delay = (time) => new Promise((resolve) => setTimeout(resolve, time));
1212

1313
// eslint-disable-next-line
1414
jasmine.DEFAULT_TIMEOUT_INTERVAL = 6e4;
1515

1616
describe('Application launch', () => {
17-
let app;
17+
let electronApp;
18+
let mainWindow;
19+
const logs = [];
1820

1921
beforeAll(async () => {
2022
await buildTestBundle();
21-
app = new Application({
22-
path: electronPath,
23-
args: ['--user-dir=__e2e__/tmp', 'dist'],
24-
env: {
25-
E2E_TEST: 1,
26-
PACKAGE: 'no',
27-
},
23+
process.env.E2E_TEST = '1';
24+
process.env.PACKAGE = 'no';
25+
electronApp = await electron.launch({
26+
executablePath,
27+
args: ['--user-dir=__e2e__/tmp', './main.js'],
28+
cwd: path.join(__dirname, '../dist'),
2829
});
29-
return app.start();
30+
mainWindow = await electronApp.firstWindow();
31+
mainWindow.on('console', (msg) => logs.push(msg));
32+
await mainWindow.waitForLoadState();
3033
});
3134

32-
afterAll(() => {
33-
if (app && app.isRunning()) {
34-
return app.stop();
35-
}
36-
});
37-
38-
it(`should be v${process.env.npm_package_version}`, async () => {
39-
// Check the App version (dist/package.json) is same with package.json
40-
const { electron } = app;
41-
const version = await electron.remote.app.getVersion();
42-
43-
// Check auto update feed is expected
44-
expect(version).toBe(process.env.npm_package_version);
45-
expect(autoUpdateFeed.url).toBe(
46-
`https://github.com/jhen0409/react-native-debugger/releases/download/v${version}/rn-debugger-macos-universal.zip`,
47-
);
48-
expect(autoUpdateFeed.name).toBe(`v${version}`);
49-
expect(typeof autoUpdateFeed.notes).toBe('string');
50-
51-
console.log(`\nAuto update notes:\n\n${autoUpdateFeed.notes}\n`);
35+
afterAll(async () => {
36+
await electronApp.close();
5237
});
5338

5439
it('should show an initial window', async () => {
55-
const { client, browserWindow } = app;
56-
57-
await client.waitUntilWindowLoaded();
58-
await delay(2000);
59-
const title = await browserWindow.getTitle();
60-
expect(title).toBe(
40+
expect(await mainWindow.title()).toBe(
6141
'React Native Debugger - Attempting reconnection (port 8081)',
6242
);
6343
});
@@ -75,35 +55,25 @@ describe('Application launch', () => {
7555
let expected = false;
7656
while (attempts > 0 && !expected) {
7757
expected = fs.existsSync(portFile);
78-
await delay(100);
58+
await delay(1000);
7959
attempts--;
8060
}
8161
expect(expected).toBe(true);
8262
});
8363

8464
it("should contain Inspector monitor's component on Redux DevTools", async () => {
85-
const { client } = app;
86-
87-
const el = await client.$('//div[contains(@class, "inspector-")]');
88-
const val = await el.getText();
65+
const val = await mainWindow.textContent('//div[contains(@class, "inspector-")]');
8966
expect(val).not.toBeNull();
9067
});
9168

9269
it('should contain an empty actions list on Redux DevTools', async () => {
93-
const { client } = app;
94-
95-
const el = await client.$('//div[contains(@class, "actionListRows-")]');
96-
const val = await el.getText();
70+
const val = await mainWindow.textContent('//div[contains(@class, "actionListRows-")]');
9771
expect(val).toBe('');
9872
});
9973

10074
it('should show waiting message on React DevTools', async () => {
101-
const { client } = app;
102-
const el = await client.$(
103-
'//h2[text()="Waiting for React to connect…"]',
104-
);
105-
const exist = await el.isExisting();
106-
expect(exist).toBe(true);
75+
const el = await mainWindow.locator('//h2[text()="Waiting for React to connect…"]');
76+
expect(await el.isVisible()).toBe(true);
10777
});
10878

10979
const customRNServerPort = 8098;
@@ -120,8 +90,7 @@ describe('Application launch', () => {
12090
const url = await getURLFromConnection(wss);
12191
expect(url).toBe('/debugger-proxy?role=debugger&name=Chrome');
12292

123-
const title = await app.browserWindow.getTitle();
124-
expect(title).toBe(
93+
expect(await mainWindow.title()).toBe(
12594
'React Native Debugger - Waiting for client connection (port 8081)',
12695
);
12796
server.close();
@@ -154,10 +123,11 @@ describe('Application launch', () => {
154123
const url = await getURLFromConnection(wss);
155124
expect(url).toBe('/debugger-proxy?role=debugger&name=Chrome');
156125

157-
const title = await app.browserWindow.getTitle();
158-
expect(title).toBe(
159-
`React Native Debugger - Waiting for client connection (port ${customRNServerPort})`,
160-
);
126+
await waitForExpect(async () => {
127+
expect(await mainWindow.title()).toBe(
128+
`React Native Debugger - Waiting for client connection (port ${customRNServerPort})`,
129+
);
130+
});
161131
server.close();
162132
wss.close();
163133
});
@@ -213,8 +183,7 @@ describe('Application launch', () => {
213183
);
214184
});
215185
});
216-
const title = await app.browserWindow.getTitle();
217-
expect(title).toBe(
186+
expect(await mainWindow.title()).toBe(
218187
`React Native Debugger - Connected (port ${customRNServerPort})`,
219188
);
220189
});
@@ -232,26 +201,23 @@ describe('Application launch', () => {
232201
});
233202

234203
it('should have @@INIT action on Redux DevTools', async () => {
235-
const { client } = app;
236-
const el = await client.$('//div[contains(@class, "actionListRows-")]');
237-
const val = await el.getText();
238-
expect(val).toMatch(/@@redux\/INIT/); // Last store is `RemoteDev store instance 1`
204+
expect(
205+
await mainWindow.textContent('//div[contains(@class, "actionListRows-")]')
206+
).toMatch(/@@redux\/INIT/); // Last store is `RemoteDev store instance 1`
239207
});
240208

241209
let currentInstance = 'Autoselect instances'; // Default instance
242210
const wait = () => delay(750);
243211
const selectInstance = async (instance) => {
244-
const { client } = app;
245-
let el = await client.$(`//div[text()="${currentInstance}"]`);
246-
await el.click().then(wait);
212+
await mainWindow.click(`//div[text()="${currentInstance}"]`);
213+
await wait();
247214
currentInstance = instance;
248-
el = await client.$(`//div[text()="${instance}"]`);
249-
return el.click().then(wait);
215+
await mainWindow.click(`//div[text()="${instance}"]`);
216+
await wait();
250217
};
251218
const commit = async () => {
252-
const { client } = app;
253-
const el = await client.$('//div[text()="Commit"]');
254-
await el.click().then(delay(100));
219+
await mainWindow.click('//div[text()="Commit"]');
220+
await wait();
255221
};
256222

257223
const expectActions = {
@@ -298,11 +264,8 @@ describe('Application launch', () => {
298264
};
299265

300266
const checkInstance = async (name) => {
301-
const { client } = app;
302-
303267
await selectInstance(name);
304-
const el = await client.$('//div[contains(@class, "actionListRows-")]');
305-
const val = await el.getText();
268+
const val = await mainWindow.textContent('//div[contains(@class, "actionListRows-")]');
306269
runExpectActions(name, val);
307270
await commit();
308271
};
@@ -322,30 +285,25 @@ describe('Application launch', () => {
322285
});
323286

324287
it('should have only specific logs in console of main window', async () => {
325-
const { client } = app;
326-
const logs = await client.getRenderProcessLogs();
327288
// Print renderer process logs
328289
logs.forEach((log) =>
329290
console.log(
330-
`Message: ${log.message}\nSource: ${log.source}\nLevel: ${log.level}`,
291+
`Message: ${log.text()}\nType: ${log.type()}`,
331292
),
332293
);
333-
expect(logs.length).toEqual(1);
334-
const [formDataWarning] = logs;
335-
expect(formDataWarning.source).toBe('worker');
336-
expect(formDataWarning.level).toBe('WARNING');
294+
expect(logs.length).toEqual(3); // clear + clear + warning
295+
const [, , formDataWarning] = logs;
296+
expect(formDataWarning.type()).toBe('warning');
337297
expect(
338-
formDataWarning.message.indexOf(
298+
formDataWarning.text().indexOf(
339299
"Detected you're enabled Network Inspect",
340300
) > 0,
341301
).toBeTruthy();
342302
});
343303

344304
it('should show apollo devtools panel', async () => {
345305
expect(
346-
await app.webContents.executeJavaScript(
347-
'window.__APOLLO_DEVTOOLS_SHOULD_DISPLAY_PANEL__'
348-
),
306+
await mainWindow.evaluate(() => window.__APOLLO_DEVTOOLS_SHOULD_DISPLAY_PANEL__),
349307
).toBeTruthy();
350308
});
351309
});

app/containers/App.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { ipcRenderer, remote } from 'electron';
1+
import { ipcRenderer } from 'electron';
2+
import { getCurrentWindow } from '@electron/remote';
23
import React, { Component } from 'react';
34
import PropTypes from 'prop-types';
45
import { bindActionCreators } from 'redux';
@@ -11,7 +12,7 @@ import FormInput from '../components/FormInput';
1112
import Draggable from '../components/Draggable';
1213
import { catchConsoleLogLink } from '../../electron/devtools';
1314

14-
const currentWindow = remote.getCurrentWindow();
15+
const currentWindow = getCurrentWindow();
1516

1617
const styles = {
1718
container: {

app/index.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { findAPortNotInUse } from 'portscanner';
2-
import { webFrame, remote } from 'electron';
2+
import { webFrame } from 'electron';
3+
import { getCurrentWindow } from '@electron/remote';
34
import React from 'react';
45
import { render } from 'react-dom';
56
import { Provider } from 'react-redux';
@@ -13,7 +14,7 @@ import { client, tryADBReverse } from './utils/adb';
1314
import config from './utils/config';
1415
import { toggleOpenInEditor, isOpenInEditorEnabled } from './utils/devtools';
1516

16-
const currentWindow = remote.getCurrentWindow();
17+
const currentWindow = getCurrentWindow();
1718

1819
webFrame.setZoomFactor(1);
1920
webFrame.setVisualZoomLevelLimits(1, 1);

app/middlewares/debuggerAPI.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
// Take from https://github.com/facebook/react-native/blob/master/local-cli/server/util/debugger.html
1111

12-
import { remote } from 'electron';
12+
import { getCurrentWindow } from '@electron/remote';
1313
import { bindActionCreators } from 'redux';
1414
import { checkPortStatus } from 'portscanner';
1515
import * as debuggerActions from '../actions/debugger';
@@ -18,7 +18,7 @@ import { tryADBReverse } from '../utils/adb';
1818
import { clearNetworkLogs, selectRNDebuggerWorkerContext } from '../utils/devtools';
1919
import config from '../utils/config';
2020

21-
const currentWindow = remote.getCurrentWindow();
21+
const currentWindow = getCurrentWindow();
2222
const { SET_DEBUGGER_LOCATION, BEFORE_WINDOW_CLOSE } = debuggerActions;
2323

2424
let worker;

0 commit comments

Comments
 (0)