Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -2145,6 +2145,11 @@ consequences, and they are rules rather than observations:
`tsx e2e/reset-profile.ts && wdio run …`. Not from a hook: nothing orders a wdio hook against
the service's own `onPrepare`, and a wipe from inside meets a living process, a locked
database and an open WAL. A separate process beforehand has no ordering to get wrong.
⚠️ The profile is **two** directories, not one: `tauri-plugin-window-state` writes
`.window-state.json` under `app_config_dir()` while everything else the application
writes lives under `app_data_dir()`. Windows cannot tell them apart, so wiping only the
data directory passed there and left the window geometry behind on Linux — where a run
then opened on the window the previous one closed with.
- **`before()` buys each file a fresh front end and nothing more.** `browser.refresh()` reboots
Angular and every store over the same database; it resets no data.
- **A spec file establishes its own preconditions.** It seeds what it needs, and it does not
Expand Down
31 changes: 27 additions & 4 deletions e2e/support/profile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,25 @@ function e2eDataDir(): string {
return xdg ? join(xdg, IDENTIFIER) : join(process.env['HOME'] ?? '', '.local/share', IDENTIFIER);
}

/**
* ⚠️ A second directory, and on Linux it is **not** the first one.
*
* `tauri-plugin-window-state` writes `.window-state.json` under `app_config_dir()`,
* while everything else the application writes lives under `app_data_dir()`. Windows
* cannot tell the two apart — both are `%APPDATA%\<identifier>` — which is why wiping
* only the data directory looked complete: on Linux the geometry survived the wipe, so
* a run inherited the window of the run before it and the first one to end on an
* unusual size handed it to every run after. CI never saw it, its runners being new
* each time; a developer running the suite twice did.
*/
function e2eConfigDir(): string {
if (process.platform === 'win32') {
return join(process.env['APPDATA'] ?? '', IDENTIFIER);
}
const xdg = process.env['XDG_CONFIG_HOME'];
return xdg ? join(xdg, IDENTIFIER) : join(process.env['HOME'] ?? '', '.config', IDENTIFIER);
}

/**
* ⚠️ Under the **data** directory, not the config one. `tauri-plugin-store` resolves a
* relative path against `BaseDirectory::AppData`, and `PreferencesService` passes it no
Expand Down Expand Up @@ -49,9 +68,12 @@ export function homeSpaceMarker(): string {
* no ordering to get wrong.
*/
export function resetProfile(): void {
const directory = e2eDataDir();
// Both, and `new Set` because on Windows they are the same path.
const directories = [...new Set([e2eDataDir(), e2eConfigDir()])];

rmSync(directory, { recursive: true, force: true });
for (const directory of directories) {
rmSync(directory, { recursive: true, force: true });
}
rmSync(homeSpaceMarker(), { force: true });

// ⚠️ `force` covers "it was not there", which is the ordinary case — but it also
Expand All @@ -62,9 +84,10 @@ export function resetProfile(): void {
// the first-launch scenario, the only one that can resolve it, had already failed.
//
// Say so here rather than let fifteen files disagree about why.
if (existsSync(directory)) {
const survivor = directories.find((directory) => existsSync(directory));
if (survivor) {
throw new Error(
`the e2e profile at ${directory} could not be wiped — an application from a previous run is probably still holding it open`,
`the e2e profile at ${survivor} could not be wiped — an application from a previous run is probably still holding it open`,
);
}
}