Merge pull request #3202 from balena-io/add-custom-protocol-2

Add custom protocol 2
This commit is contained in:
bulldozer-balena[bot] 2020-06-08 15:05:57 +00:00 committed by GitHub
commit b7ad7bd729
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 260 additions and 80 deletions

View File

@ -62,6 +62,12 @@
"depends": [
"polkit-1-auth-agent | policykit-1-gnome | polkit-kde-1"
]
},
"protocols": {
"name": "etcher",
"schemes": [
"etcher"
]
}
}
}

View File

@ -164,10 +164,8 @@ lint: lint-ts lint-sass lint-cpp lint-spell
MOCHA_OPTIONS=--recursive --reporter spec --require ts-node/register --require-main "tests/gui/allow-renderer-process-reuse.ts"
# See https://github.com/electron/spectron/issues/127
ETCHER_SPECTRON_ENTRYPOINT ?= $(shell node -e 'console.log(require("electron"))')
test-spectron:
ETCHER_SPECTRON_ENTRYPOINT="$(ETCHER_SPECTRON_ENTRYPOINT)" mocha $(MOCHA_OPTIONS) tests/spectron/runner.spec.ts
mocha $(MOCHA_OPTIONS) tests/spectron/runner.spec.ts
test-gui:
electron-mocha $(MOCHA_OPTIONS) --full-trace --no-sandbox --renderer tests/gui/**/*.ts

View File

@ -1,10 +1,11 @@
'use strict'
const { notarize } = require('electron-notarize')
const { ELECTRON_SKIP_NOTARIZATION } = process.env
async function main(context) {
const { electronPlatformName, appOutDir } = context
if (electronPlatformName !== 'darwin') {
if (electronPlatformName !== 'darwin' || ELECTRON_SKIP_NOTARIZATION === 'true') {
return
}

View File

@ -1,17 +1,26 @@
'use strict'
const cp = require('child_process')
const cp = require('child_process');
const rimraf = require('rimraf');
const process = require('process');
// Rebuild native modules for ia32 and run webpack again for the ia32 part of windows packages
exports.default = function(context) {
if (context.platform.name === 'windows') {
cp.execFileSync(
'bash',
['./node_modules/.bin/electron-rebuild', '--types', 'dev', '--arch', context.arch]
['./node_modules/.bin/electron-rebuild', '--types', 'dev', '--arch', context.arch],
);
rimraf.sync('generated');
cp.execFileSync(
'bash',
['./node_modules/.bin/webpack']
['./node_modules/.bin/webpack'],
{
env: {
...process.env,
npm_config_target_arch: context.arch,
},
},
);
}
}

View File

@ -91,3 +91,7 @@ deb:
rpm:
depends:
- util-linux
protocols:
name: etcher
schemes:
- etcher

View File

@ -17,6 +17,7 @@
import { faFile, faLink } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { sourceDestination } from 'etcher-sdk';
import { ipcRenderer, IpcRendererEvent } from 'electron';
import * as _ from 'lodash';
import { GPTPartition, MBRPartition } from 'partitioninfo';
import * as path from 'path';
@ -237,6 +238,7 @@ export class SourceSelector extends React.Component<
this.openImageSelector = this.openImageSelector.bind(this);
this.openURLSelector = this.openURLSelector.bind(this);
this.reselectImage = this.reselectImage.bind(this);
this.onSelectImage = this.onSelectImage.bind(this);
this.onDrop = this.onDrop.bind(this);
this.showSelectedImageDetails = this.showSelectedImageDetails.bind(this);
this.afterSelected = props.afterSelected.bind(this);
@ -246,10 +248,22 @@ export class SourceSelector extends React.Component<
this.unsubscribe = observe(() => {
this.setState(getState());
});
ipcRenderer.on('select-image', this.onSelectImage);
ipcRenderer.send('source-selector-ready');
}
public componentWillUnmount() {
this.unsubscribe();
ipcRenderer.removeListener('select-image', this.onSelectImage);
}
private async onSelectImage(_event: IpcRendererEvent, imagePath: string) {
const isURL =
_.startsWith(imagePath, 'https://') || _.startsWith(imagePath, 'http://');
await this.selectImageByPath({
imagePath,
SourceType: isURL ? sourceDestination.Http : sourceDestination.File,
});
}
private reselectImage() {

View File

@ -17,6 +17,7 @@
import { delay } from 'bluebird';
import * as electron from 'electron';
import { autoUpdater } from 'electron-updater';
import { platform } from 'os';
import * as _ from 'lodash';
import * as path from 'path';
import * as semver from 'semver';
@ -28,6 +29,8 @@ import * as settings from './app/models/settings';
import * as analytics from './app/modules/analytics';
import { buildWindowMenu } from './menu';
const customProtocol = 'etcher';
const scheme = `${customProtocol}://`;
const updatablePackageTypes = ['appimage', 'nsis', 'dmg'];
const packageUpdatable = _.includes(updatablePackageTypes, packageType);
let packageUpdated = false;
@ -54,6 +57,44 @@ async function checkForUpdates(interval: number) {
}
}
function getCommandLineURL(argv: string[]): string | undefined {
argv = argv.slice(electron.app.isPackaged ? 1 : 2);
if (argv.length) {
const value = argv[argv.length - 1];
// Take into account electron arguments
if (value.startsWith('--')) {
return;
}
// https://stackoverflow.com/questions/10242115/os-x-strange-psn-command-line-parameter-when-launched-from-finder
if (platform() === 'darwin' && value.startsWith('-psn_')) {
return;
}
return value;
}
}
const sourceSelectorReady = new Promise((resolve) => {
electron.ipcMain.on('source-selector-ready', resolve);
});
async function selectImageURL(url?: string) {
// 'data:,' is the default chromedriver url that is passed as last argument when running spectron tests
if (url !== undefined && url !== 'data:,') {
url = url.startsWith(scheme) ? url.slice(scheme.length) : url;
await sourceSelectorReady;
electron.BrowserWindow.getAllWindows().forEach((window) => {
window.webContents.send('select-image', url);
});
}
}
// This will catch clicks on links such as <a href="etcher://...">Open in Etcher</a>
// We need to listen to the event before everything else otherwise the event won't be fired
electron.app.on('open-url', async (event, data) => {
event.preventDefault();
await selectImageURL(data);
});
async function createMainWindow() {
const fullscreen = Boolean(await settings.get('fullscreen'));
const defaultWidth = 800;
@ -87,6 +128,8 @@ async function createMainWindow() {
},
});
electron.app.setAsDefaultProtocolClient(customProtocol);
buildWindowMenu(mainWindow);
mainWindow.setFullScreen(true);
@ -133,6 +176,7 @@ async function createMainWindow() {
}
}
});
return mainWindow;
}
electron.app.allowRendererProcessReuse = false;
@ -145,14 +189,24 @@ electron.app.on('window-all-closed', electron.app.quit);
// make use of it to ensure the browser window is completely destroyed.
// See https://github.com/electron/electron/issues/5273
electron.app.on('before-quit', () => {
electron.app.releaseSingleInstanceLock();
process.exit(EXIT_CODES.SUCCESS);
});
async function main(): Promise<void> {
if (electron.app.isReady()) {
await createMainWindow();
if (!electron.app.requestSingleInstanceLock()) {
electron.app.quit();
} else {
electron.app.on('ready', createMainWindow);
await electron.app.whenReady();
const window = await createMainWindow();
electron.app.on('second-instance', async (_event, argv) => {
if (window.isMinimized()) {
window.restore();
}
window.focus();
await selectImageURL(getCommandLineURL(argv));
});
await selectImageURL(getCommandLineURL(process.argv));
}
}

View File

@ -246,7 +246,7 @@ ipc.connectTo(IPC_SERVER_ID, () => {
path: options.imagePath,
});
} else {
source = new Http({ url: options.imagePath });
source = new Http({ url: options.imagePath, avoidRandomAccess: true });
}
try {
const results = await writeAndValidate({

View File

@ -29,7 +29,10 @@ import { tmpFileDisposer } from './utils';
const execAsync = promisify(childProcess.exec);
const execFileAsync = promisify(childProcess.execFile);
const sudoExecAsync = promisify(sudoPrompt.exec);
// sudo-prompt's exec callback is function(error, stdout, stderr) so we need multiArgs
const sudoExecAsync = Bluebird.promisify(sudoPrompt.exec, {
multiArgs: true,
}) as (cmd: string, options: any) => Bluebird<[string, string]>;
/**
* @summary The user id of the UNIX "superuser"
@ -123,10 +126,7 @@ async function elevateScriptUnix(
name: string,
): Promise<{ cancelled: boolean }> {
const cmd = ['bash', escapeSh(path)].join(' ');
const [, stderr] = await sudoExecAsync(cmd, { name });
if (!_.isEmpty(stderr)) {
throw errors.createError({ title: stderr });
}
await sudoExecAsync(cmd, { name });
return { cancelled: false };
}

159
npm-shrinkwrap.json generated
View File

@ -677,6 +677,16 @@
"integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
"dev": true
},
"@types/copy-webpack-plugin": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/@types/copy-webpack-plugin/-/copy-webpack-plugin-6.0.0.tgz",
"integrity": "sha512-Ousy+sNap1j44eG+C9FZvTUybpp9lFmKjBRF7L0NDs/+SDA9OXKo2OpsHJfD/LMWflz+uvfTCBXH1CgdL6AW/g==",
"dev": true,
"requires": {
"@types/node": "*",
"@types/webpack": "*"
}
},
"@types/debug": {
"version": "4.1.5",
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz",
@ -965,13 +975,13 @@
}
},
"@types/terser-webpack-plugin": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@types/terser-webpack-plugin/-/terser-webpack-plugin-2.2.0.tgz",
"integrity": "sha512-ywqEfTm7KdKoX9aYx0zYtiFU1z6IHrIYW9FJqeay2Ea58rTPML1J0hvoztGal2Jow3bkgGKcAmEZNL+8LqUVrA==",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@types/terser-webpack-plugin/-/terser-webpack-plugin-3.0.0.tgz",
"integrity": "sha512-K5C7izOT8rR4qiE2vfXcQNEJN4lT9cq/2qJgpMUWR2HsjDW/KVrHx2CaHuaXvaqDNsRmdELPLaxeJHiI4GjVrA==",
"dev": true,
"requires": {
"@types/webpack": "*",
"terser": "^4.3.9"
"terser": "^4.6.13"
}
},
"@types/tmp": {
@ -4325,9 +4335,9 @@
"dev": true
},
"drivelist": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/drivelist/-/drivelist-9.0.0.tgz",
"integrity": "sha512-DNQ1oFAv5p1+UKVkQHCYQFHolFbItxSnjcJchxrhlEkW4RSuLfC0xOnq87uM8dcMzOuPfA37SKX7HsUIpw14uA==",
"version": "9.0.2",
"resolved": "https://registry.npmjs.org/drivelist/-/drivelist-9.0.2.tgz",
"integrity": "sha512-B68AttNDXsew8M2viM99I4sNMJ2T5/lZ2fDlVsEAAzaJ1pyZN2Ibhhd37LAqsNRPhhPtpyrCi9+C6AfJ2kwo4g==",
"dev": true,
"requires": {
"bindings": "^1.3.0",
@ -4402,9 +4412,9 @@
}
},
"electron": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/electron/-/electron-9.0.0.tgz",
"integrity": "sha512-JsaSQNPh+XDYkLj8APtVKTtvpb86KIG57W5OOss4TNrn8L3isC9LsCITwfnVmGIXHhvX6oY/weCtN5hAAytjVg==",
"version": "9.0.2",
"resolved": "https://registry.npmjs.org/electron/-/electron-9.0.2.tgz",
"integrity": "sha512-+a3KegLvQXVjC3b6yBWwZmtWp3tHf9ut27yORAWHO9JRFtKfNf88fi1UvTPJSW8R0sUH7ZEdzN6A95T22KGtlA==",
"dev": true,
"requires": {
"@electron/get": "^1.0.1",
@ -4756,6 +4766,25 @@
"path-exists": "^3.0.0"
}
},
"node-gyp": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-6.1.0.tgz",
"integrity": "sha512-h4A2zDlOujeeaaTx06r4Vy+8MZ1679lU+wbCKDS4ZtvY2A37DESo37oejIw0mtmR3+rvNwts5B6Kpt1KrNYdNw==",
"dev": true,
"requires": {
"env-paths": "^2.2.0",
"glob": "^7.1.4",
"graceful-fs": "^4.2.2",
"mkdirp": "^0.5.1",
"nopt": "^4.0.1",
"npmlog": "^4.1.2",
"request": "^2.88.0",
"rimraf": "^2.6.3",
"semver": "^5.7.1",
"tar": "^4.4.12",
"which": "^1.3.1"
}
},
"p-locate": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
@ -4771,6 +4800,12 @@
"integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
"dev": true
},
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true
},
"string-width": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
@ -5320,9 +5355,9 @@
"dev": true
},
"etcher-sdk": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/etcher-sdk/-/etcher-sdk-4.1.4.tgz",
"integrity": "sha512-s9KXeLOtwrOxZs6F2VpGdS2VARwgJzmQp7/Xh4DG0yTAIR58djzZ2+cmUQQN16ztFMiQdCgTWWnOUJV1eVtO4g==",
"version": "4.1.8",
"resolved": "https://registry.npmjs.org/etcher-sdk/-/etcher-sdk-4.1.8.tgz",
"integrity": "sha512-fSNwpqeCdc75xNIKwf+At8+r/EQ+/X/IV7gUYFa/wKXtnFHHxYJor6VfPdELUbtDDBWWa2cneJvtwGmcDPBAvA==",
"dev": true,
"requires": {
"@ronomon/direct-io": "^3.0.1",
@ -9454,9 +9489,9 @@
}
},
"node-addon-api": {
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.1.tgz",
"integrity": "sha512-2+DuKodWvwRTrCfKOeR24KIc5unKjOh8mz17NCzVnHWfjAdDqbfbjqh7gUT+BkXBRQM52+xCHciKWonJ3CbJMQ==",
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz",
"integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==",
"dev": true
},
"node-environment-flags": {
@ -9488,28 +9523,90 @@
}
},
"node-gyp": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-6.1.0.tgz",
"integrity": "sha512-h4A2zDlOujeeaaTx06r4Vy+8MZ1679lU+wbCKDS4ZtvY2A37DESo37oejIw0mtmR3+rvNwts5B6Kpt1KrNYdNw==",
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-7.0.0.tgz",
"integrity": "sha512-ZW34qA3CJSPKDz2SJBHKRvyNQN0yWO5EGKKksJc+jElu9VA468gwJTyTArC1iOXU7rN3Wtfg/CMt/dBAOFIjvg==",
"dev": true,
"requires": {
"env-paths": "^2.2.0",
"glob": "^7.1.4",
"graceful-fs": "^4.2.2",
"mkdirp": "^0.5.1",
"nopt": "^4.0.1",
"graceful-fs": "^4.2.3",
"nopt": "^4.0.3",
"npmlog": "^4.1.2",
"request": "^2.88.0",
"request": "^2.88.2",
"rimraf": "^2.6.3",
"semver": "^5.7.1",
"tar": "^4.4.12",
"which": "^1.3.1"
"semver": "^7.3.2",
"tar": "^6.0.1",
"which": "^2.0.2"
},
"dependencies": {
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"chownr": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
"dev": true
},
"fs-minipass": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
"integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
"dev": true,
"requires": {
"minipass": "^3.0.0"
}
},
"minipass": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz",
"integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==",
"dev": true,
"requires": {
"yallist": "^4.0.0"
}
},
"minizlib": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.0.tgz",
"integrity": "sha512-EzTZN/fjSvifSX0SlqUERCN39o6T40AMarPbv0MrarSFtIITCBh7bi+dU8nxGFHuqs9jdIAeoYoKuQAAASsPPA==",
"dev": true,
"requires": {
"minipass": "^3.0.0",
"yallist": "^4.0.0"
}
},
"mkdirp": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
"dev": true
},
"tar": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.0.2.tgz",
"integrity": "sha512-Glo3jkRtPcvpDlAs/0+hozav78yoXKFr+c4wgw62NNMO3oo4AaJdCo21Uu7lcwr55h39W2XD1LMERc64wtbItg==",
"dev": true,
"requires": {
"chownr": "^2.0.0",
"fs-minipass": "^2.0.0",
"minipass": "^3.0.0",
"minizlib": "^2.1.0",
"mkdirp": "^1.0.3",
"yallist": "^4.0.0"
}
},
"which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dev": true,
"requires": {
"isexe": "^2.0.0"
}
},
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
}
}
@ -14963,4 +15060,4 @@
}
}
}
}
}

View File

@ -51,6 +51,7 @@
"@fortawesome/react-fontawesome": "^0.1.7",
"@types/bluebird": "^3.5.30",
"@types/chai": "^4.2.7",
"@types/copy-webpack-plugin": "^6.0.0",
"@types/mime-types": "^2.1.0",
"@types/mini-css-extract-plugin": "^0.9.1",
"@types/mocha": "^7.0.2",
@ -60,7 +61,7 @@
"@types/request": "^2.48.4",
"@types/semver": "^7.1.0",
"@types/sinon": "^9.0.0",
"@types/terser-webpack-plugin": "^2.2.0",
"@types/terser-webpack-plugin": "^3.0.0",
"@types/tmp": "^0.2.0",
"@types/webpack-node-externals": "^1.7.0",
"bluebird": "^3.7.2",
@ -70,13 +71,13 @@
"css-loader": "^3.5.3",
"d3": "^4.13.0",
"debug": "^4.2.0",
"electron": "9.0.0",
"electron": "9.0.2",
"electron-builder": "^22.7.0",
"electron-mocha": "^8.2.0",
"electron-notarize": "^0.3.0",
"electron-rebuild": "^1.11.0",
"electron-updater": "^4.3.2",
"etcher-sdk": "^4.1.4",
"etcher-sdk": "^4.1.8",
"file-loader": "^6.0.0",
"flexboxgrid": "^6.3.0",
"husky": "^4.2.5",
@ -89,7 +90,7 @@
"mocha": "^7.0.1",
"nan": "^2.14.0",
"native-addon-loader": "^2.0.1",
"node-gyp": "^6.1.0",
"node-gyp": "^7.0.0",
"node-ipc": "^9.1.1",
"omit-deep-lodash": "1.1.4",
"path-is-inside": "^1.0.2",

View File

@ -16,41 +16,29 @@
import { expect } from 'chai';
import { Application } from 'spectron';
import * as EXIT_CODES from '../../lib/shared/exit-codes';
const entrypoint = process.env.ETCHER_SPECTRON_ENTRYPOINT;
if (!entrypoint) {
console.error('You need to properly configure ETCHER_SPECTRON_ENTRYPOINT');
process.exit(EXIT_CODES.GENERAL_ERROR);
}
import * as electronPath from 'electron';
describe('Spectron', function () {
// Mainly for CI jobs
this.timeout(40000);
let app: Application;
before('app:start', function () {
app = new Application({
path: entrypoint,
args: ['--no-sandbox', '.'],
});
return app.start();
const app = new Application({
path: (electronPath as unknown) as string,
args: ['--no-sandbox', '.'],
});
after('app:stop', function () {
before('app:start', async () => {
await app.start();
});
after('app:stop', async () => {
if (app && app.isRunning()) {
return app.stop();
await app.stop();
}
return Promise.resolve();
});
describe('Browser Window', function () {
it('should open a browser window', async function () {
describe('Browser Window', () => {
it('should open a browser window', async () => {
// We can't use `isVisible()` here as it won't work inside
// a Windows Docker container, but we can approximate it
// with these set of checks:
@ -61,7 +49,7 @@ describe('Spectron', function () {
expect(await app.browserWindow.isFocused()).to.be.true;
});
it('should set a proper title', async function () {
it('should set a proper title', async () => {
// @ts-ignore (SpectronClient.getTitle exists)
return expect(await app.client.getTitle()).to.equal('Etcher');
});

View File

@ -14,7 +14,6 @@
* limitations under the License.
*/
// @ts-ignore @types for copy-webpack-plugin@6.0.1 not released yet
import * as CopyPlugin from 'copy-webpack-plugin';
import { readdirSync } from 'fs';
import * as _ from 'lodash';
@ -22,6 +21,7 @@ import * as MiniCssExtractPlugin from 'mini-css-extract-plugin';
import * as os from 'os';
import outdent from 'outdent';
import * as path from 'path';
import { env } from 'process';
import * as SimpleProgressWebpackPlugin from 'simple-progress-webpack-plugin';
import * as TerserPlugin from 'terser-webpack-plugin';
import { BannerPlugin, NormalModuleReplacementPlugin } from 'webpack';
@ -77,7 +77,11 @@ function renameNodeModules(resourcePath: string) {
function findLzmaNativeBindingsFolder(): string {
const files = readdirSync(path.join('node_modules', 'lzma-native'));
const bindingsFolder = files.find((f) => f.startsWith('binding-'));
const bindingsFolder = files.find(
(f) =>
f.startsWith('binding-') &&
f.endsWith(env.npm_config_target_arch || os.arch()),
);
if (bindingsFolder === undefined) {
throw new Error('Could not find lzma_native binding');
}
@ -91,11 +95,15 @@ interface ReplacementRule {
replace: string | (() => string);
}
function slashOrAntislash(pattern: RegExp): RegExp {
return new RegExp(pattern.source.replace(/\\\//g, '(\\/|\\\\)'));
}
function replace(test: RegExp, ...replacements: ReplacementRule[]) {
return {
loader: 'string-replace-loader',
// Handle windows path separators
test: new RegExp(test.source.replace(/\\\//g, '(\\/|\\\\)')),
test: slashOrAntislash(test),
options: { multiple: replacements.map((r) => ({ ...r, strict: true })) },
};
}
@ -218,7 +226,7 @@ const commonConfig = {
// Force axios to use http.js, not xhr.js as we need stream support
// (it's package.json file replaces http with xhr for browser targets).
new NormalModuleReplacementPlugin(
/node_modules\/axios\/lib\/adapters\/xhr\.js/,
slashOrAntislash(/node_modules\/axios\/lib\/adapters\/xhr\.js/),
'./http.js',
),
],