diff --git a/packages/app-desktop/ElectronAppWrapper.ts b/packages/app-desktop/ElectronAppWrapper.ts index 989c5be9b0..ba76b492bc 100644 --- a/packages/app-desktop/ElectronAppWrapper.ts +++ b/packages/app-desktop/ElectronAppWrapper.ts @@ -36,12 +36,21 @@ interface SecondaryWindowData { electronId: number; } +export interface Options { + env: string; + profilePath: string|null; + isDebugMode: boolean; + isEndToEndTesting: boolean; + initialCallbackUrl: string; +} + export default class ElectronAppWrapper { private logger_: Logger = null; private electronApp_: App; private env_: string; private isDebugMode_: boolean; private profilePath_: string; + private isEndToEndTesting_: boolean; private win_: BrowserWindow = null; private mainWindowHidden_ = true; @@ -65,12 +74,13 @@ export default class ElectronAppWrapper { private ipcLogger_: Logger; - public constructor(electronApp: App, env: string, profilePath: string|null, isDebugMode: boolean, initialCallbackUrl: string) { + public constructor(electronApp: App, { env, profilePath, isDebugMode, initialCallbackUrl, isEndToEndTesting }: Options) { this.electronApp_ = electronApp; this.env_ = env; this.isDebugMode_ = isDebugMode; this.profilePath_ = profilePath; this.initialCallbackUrl_ = initialCallbackUrl; + this.isEndToEndTesting_ = isEndToEndTesting; this.profileLocker_ = new FileLocker(`${this.profilePath_}/lock`); @@ -576,7 +586,9 @@ export default class ElectronAppWrapper { } public async ensureSingleInstance() { - // if (this.env_ === 'dev') return false; + // When end-to-end testing, multiple instances of Joplin are intentionally created at the same time, + // or very close to one another. The single instance handling logic can interfere with this, so disable it. + if (this.isEndToEndTesting_) return false; interface OnSecondInstanceMessageData { profilePath: string; diff --git a/packages/app-desktop/integration-tests/util/createStartupArgs.ts b/packages/app-desktop/integration-tests/util/createStartupArgs.ts index 60fcd5fad2..e499861a8a 100644 --- a/packages/app-desktop/integration-tests/util/createStartupArgs.ts +++ b/packages/app-desktop/integration-tests/util/createStartupArgs.ts @@ -7,7 +7,7 @@ const createStartupArgs = (profileDirectory: string) => { // We need to run with --env dev to disable the single instance check. return [ - mainPath, '--env', 'dev', '--no-welcome', '--profile', resolve(profileDirectory), + mainPath, '--env', 'dev', '--no-welcome', '--running-tests', '--profile', resolve(profileDirectory), ]; }; diff --git a/packages/app-desktop/main.js b/packages/app-desktop/main.js index 32f1b1d99f..4d2f129f58 100644 --- a/packages/app-desktop/main.js +++ b/packages/app-desktop/main.js @@ -38,6 +38,7 @@ Logger.fsDriver_ = new FsDriverNode(); const env = envFromArgs(process.argv); const profileFromArgs = getFlagValueFromArgs(process.argv, '--profile', null); const isDebugMode = !!process.argv && process.argv.indexOf('--debug') >= 0; +const isEndToEndTesting = !!process.argv?.includes('--running-tests'); const altInstanceId = getFlagValueFromArgs(process.argv, '--alt-instance-id', ''); // We initialize all these variables here because they are needed from the main process. They are @@ -64,7 +65,9 @@ void registerCustomProtocols(); const initialCallbackUrl = process.argv.find((arg) => isCallbackUrl(arg)); -const wrapper = new ElectronAppWrapper(electronApp, env, rootProfileDir, isDebugMode, initialCallbackUrl); +const wrapper = new ElectronAppWrapper(electronApp, { + env, profilePath: rootProfileDir, isDebugMode, initialCallbackUrl, isEndToEndTesting, +}); initBridge(wrapper, appId, appName, rootProfileDir, autoUploadCrashDumps, altInstanceId); diff --git a/packages/lib/utils/processStartFlags.ts b/packages/lib/utils/processStartFlags.ts index bda8456093..4f437cc7f6 100644 --- a/packages/lib/utils/processStartFlags.ts +++ b/packages/lib/utils/processStartFlags.ts @@ -188,6 +188,12 @@ const processStartFlags = async (argv: string[], setDefaults = true) => { continue; } + if (arg === '--running-tests') { + // Used by the desktop app to indicate that the app is running end-to-end tests. + argv.splice(0, 1); + continue; + } + if (arg.length && arg[0] === '-') { throw new JoplinError(_('Unknown flag: %s', arg), 'flagError'); } else {