Desktop apps
Test macOS apps and Electron apps on a Mac, and set up the permissions they need.
Retest tests two kinds of desktop app. A native macOS app is driven through XCTest. An Electron app is driven through its own Chromium, like a browser.
macOS apps Link to macOS apps
const config = defineConfig({ apps: { desk: { platform: 'macos', appPath: './TaskDesk.app', arguments: ['-reset', '-windowFrame', '20,60,700,480'], environment: { TASK_MODE: 'test' }, }, },})A macOS app needs three things on the Mac that runs it:
- The macOS executor, built with
npx retest install mac2. It is pinned to Xcode 26.5 on Apple silicon. - Automation Mode enabled without a prompt. A prompt counts as a refusal. On a Mac that runs tests unattended, run
sudo automationmodetool enable-automationmode-without-authenticationonce. - Screen Recording for the terminal or agent that runs Retest, so it can capture the app's window.
Elements of a macOS app take click(), fill(), press() and scroll(), and the page has alert.accept() and alert.dismiss(). There is no goto, swipe or software keyboard, and calling one is a type error.
Window capture Link to Window capture
Retest captures the app's own window, by its window number. Another app's window over it is neither in the picture nor a reason to refuse it.
For a config with a macOS app, retest doctor adds a row for Screen Recording. It asks macOS without a prompt and takes no picture. An iOS simulator app or a browser needs no such permission.
One desktop at a time Link to One desktop at a time
A Mac has one desktop, and native input goes through it. Retest holds the desktop for one macOS app at a time, across every Retest process on the Mac. A test that needs two macOS apps is refused before it starts.
While a test drives the desktop, macOS shows its Automation Mode overlay over the screen. Run desktop tests on a Mac nobody is using at the time.
What a macOS test keeps Link to What a macOS test keeps
- The app's data and keychain are kept from one test to the next.
- An argument such as
-resetasks the app for its own reset, when it has one. - Retest never takes over or ends a copy of the app it did not launch.
Electron apps Link to Electron apps
import { defineConfig, electron } from '@rehearsal-labs/retest'export default defineConfig({ apps: { desktop: electron({ executablePath: 'electron/dist/Electron.app/Contents/MacOS/Electron', appPath: 'desktop' }), },})executablePathis the Electron binary.appPathis the app's folder, which holds itspackage.json, or its entry file.- Each test launches the app afresh and quits it when the test ends.
- The first window the app opens is the test's page. A test cannot reach any window after the first.
- Each launch gets a new data folder, removed afterwards. With
userDataDir, every launch uses that folder, so the app keeps its data. - The app's windows open on your screen. Electron has no headless mode.
Retest refuses by name what it cannot reach: goto, which is also a type error, the main process, native menus and native dialogs. A sign-in state cannot be restored into an Electron app, so use userDataDir to keep one.
A secret is typed into an Electron window only on an http or https origin that secretOrigins lists for it. Naming an origin there means trusting the app with the secret.
Electron support was checked with Electron 44.5.1 on macOS on Apple silicon. Linux, Windows and packaged apps have not been run.