diff --git a/.eslintignore b/.eslintignore index d0114686c..863f9c914 100644 --- a/.eslintignore +++ b/.eslintignore @@ -383,6 +383,8 @@ packages/app-desktop/integration-tests/models/MainScreen.js packages/app-desktop/integration-tests/models/NoteEditorScreen.js packages/app-desktop/integration-tests/models/SettingsScreen.js packages/app-desktop/integration-tests/util/activateMainMenuItem.js +packages/app-desktop/integration-tests/util/createStartupArgs.js +packages/app-desktop/integration-tests/util/firstNonDevToolsWindow.js packages/app-desktop/integration-tests/util/test.js packages/app-desktop/playwright.config.js packages/app-desktop/plugins/GotoAnything.js diff --git a/.gitignore b/.gitignore index 2e5be75bf..40bfae829 100644 --- a/.gitignore +++ b/.gitignore @@ -365,6 +365,8 @@ packages/app-desktop/integration-tests/models/MainScreen.js packages/app-desktop/integration-tests/models/NoteEditorScreen.js packages/app-desktop/integration-tests/models/SettingsScreen.js packages/app-desktop/integration-tests/util/activateMainMenuItem.js +packages/app-desktop/integration-tests/util/createStartupArgs.js +packages/app-desktop/integration-tests/util/firstNonDevToolsWindow.js packages/app-desktop/integration-tests/util/test.js packages/app-desktop/playwright.config.js packages/app-desktop/plugins/GotoAnything.js diff --git a/packages/app-desktop/integration-tests/main.spec.ts b/packages/app-desktop/integration-tests/main.spec.ts index e76ed903f..b1fcb6280 100644 --- a/packages/app-desktop/integration-tests/main.spec.ts +++ b/packages/app-desktop/integration-tests/main.spec.ts @@ -5,6 +5,8 @@ import SettingsScreen from './models/SettingsScreen'; import { _electron as electron } from '@playwright/test'; import { writeFile } from 'fs-extra'; import { join } from 'path'; +import createStartupArgs from './util/createStartupArgs'; +import firstNonDevToolsWindow from './util/firstNonDevToolsWindow'; test.describe('main', () => { @@ -130,11 +132,9 @@ test.describe('main', () => { // We need to write to the force-safe-mode file before opening the Electron app. // Open the app ourselves: - const startupArgs = [ - 'main.js', '--env', 'dev', '--profile', profileDirectory, - ]; + const startupArgs = createStartupArgs(profileDirectory); const electronApp = await electron.launch({ args: startupArgs }); - const mainWindow = await electronApp.firstWindow(); + const mainWindow = await firstNonDevToolsWindow(electronApp); const safeModeDisableLink = mainWindow.getByText('Disable safe mode and restart'); await safeModeDisableLink.waitFor(); diff --git a/packages/app-desktop/integration-tests/util/createStartupArgs.ts b/packages/app-desktop/integration-tests/util/createStartupArgs.ts new file mode 100644 index 000000000..f2397054d --- /dev/null +++ b/packages/app-desktop/integration-tests/util/createStartupArgs.ts @@ -0,0 +1,9 @@ + +const createStartupArgs = (profileDirectory: string) => { + // We need to run with --env dev to disable the single instance check. + return [ + 'main.js', '--env', 'dev', '--profile', profileDirectory, + ]; +}; + +export default createStartupArgs; diff --git a/packages/app-desktop/integration-tests/util/firstNonDevToolsWindow.ts b/packages/app-desktop/integration-tests/util/firstNonDevToolsWindow.ts new file mode 100644 index 000000000..9b09d6064 --- /dev/null +++ b/packages/app-desktop/integration-tests/util/firstNonDevToolsWindow.ts @@ -0,0 +1,43 @@ +import { ElectronApplication, Page } from '@playwright/test'; + +const isDevTools = async (page: Page) => { + // It seems that the developer tools window can have titles in different + // formats (e.g. DevTools, Developer Tools). + return (await page.title()).match(/Dev(eloper)?\s*Tools/i); +}; + +const firstNonDevToolsWindow = async (electronApp: ElectronApplication) => { + // Wait for the window event as soon as possible -- it's possible that + // the window we want will be shown while doing other async checks. + const nextNonDevToolsPage = electronApp.waitForEvent('window', { + predicate: async page => { + return !(await isDevTools(page)); + }, + }); + + // First use firstWindow -- it's possible that the first window + // has already been shown. + let mainWindow = await electronApp.firstWindow(); + + if (await isDevTools(mainWindow)) { + for (const window of electronApp.windows()) { + if (!(await isDevTools(window))) { + mainWindow = window; + break; + } + } + + if (await isDevTools(mainWindow)) { + mainWindow = await nextNonDevToolsPage; + } + } + + // waitForEvent will throw if no additional windows are created. + // Ignore. + // eslint-disable-next-line promise/prefer-await-to-then + nextNonDevToolsPage.catch(_error => {}); + + return mainWindow; +}; + +export default firstNonDevToolsWindow; diff --git a/packages/app-desktop/integration-tests/util/test.ts b/packages/app-desktop/integration-tests/util/test.ts index bd0c136d6..f3c3a2e0b 100644 --- a/packages/app-desktop/integration-tests/util/test.ts +++ b/packages/app-desktop/integration-tests/util/test.ts @@ -2,6 +2,8 @@ import { resolve, join, dirname } from 'path'; import { remove, mkdirp } from 'fs-extra'; import { _electron as electron, Page, ElectronApplication, test as base } from '@playwright/test'; import uuid from '@joplin/lib/uuid'; +import createStartupArgs from './createStartupArgs'; +import firstNonDevToolsWindow from './firstNonDevToolsWindow'; @@ -32,9 +34,7 @@ export const test = base.extend({ }, electronApp: async ({ profileDirectory }, use) => { - const startupArgs = [ - 'main.js', '--env', 'dev', '--profile', profileDirectory, - ]; + const startupArgs = createStartupArgs(profileDirectory); const electronApp = await electron.launch({ args: startupArgs }); await use(electronApp); @@ -44,8 +44,8 @@ export const test = base.extend({ }, mainWindow: async ({ electronApp }, use) => { - const window = await electronApp.firstWindow(); - await use(window); + const mainWindow = await firstNonDevToolsWindow(electronApp); + await use(mainWindow); }, });