Skip to content

Add end-to-end tests that boot the real desktop app #188

Description

@utof

Problem

Four runtime-only defects reached a working build in a single session, none of which any existing gate could catch:

Defect Symptom
set_provider_key sent api_key instead of apiKey Saving an API key in Settings always failed
cancel_transcription sent request_uuid instead of requestUuid Cancel silently non-functional
transcribe sent file_uuid / file_name / language_hint Transcribe button always failed
Provider registry is built once in build_container Saving a key in Settings has no effect until the app is relaunched

The first three are one bug class (Tauri exposes snake_case Rust params to JS as camelCase unless rename_all opts out) and are now closed by a static cross-check — see apps/desktop/src/__tests__/ipc-contract.test.ts, which derives the command list from lib.rs's invoke_handler and fails on its own parser blind spots.

The fourth is not catchable that way, and neither is anything else that depends on a booted app.

Why the existing gates can't cover this

  • tsc -b — invoke args are typed Record<string, unknown>; anything type-checks.
  • just bindingsbindings.ts is tauri-specta's type output only. It emits no command wrappers, so argument names are never inspected.
  • Component tests — mock ../api wholesale, so no payload is ever observed.
  • ipc-contract.test.ts — static source cross-check. Catches name mismatches; cannot catch runtime wiring.

Uncovered surface

Everything requiring a real process:

  • Keyring round-trip: save in Settings, relaunch, key still resolves.
  • build_container startup wiring: config + keyring produce a registered, active backend.
  • Config directory resolution — desktop reads <app_data_dir>/config.toml while the CLI reads <XDG_CONFIG>/perima/config.toml. GH CLI and desktop write to different SQLite databases on the same machine #154 unified the database path for both shells; config was not included, so the two can silently diverge.
  • Cancel semantics against a real in-flight job.
  • ffmpeg sidecar resolution (desktop uses the Tauri sidecar; the CLI uses which::which) — these are different code paths and only one is exercised today.

Proposal

Stand up tauri-driver + WebdriverIO against a debug build, covering at minimum:

  1. Settings → enter key → save → relaunch → key persists and the provider is active.
  2. Select a file → transcribe → terminal event observed (stubbed provider endpoint, no live API calls in CI).
  3. Cancel an in-flight job → app returns to idle.

Needs research before committing to an approach. Open questions: tauri-driver maturity on Linux (WebKitWebDriver), whether it runs headless on GitHub runners, how to point the app at a stub transcription endpoint without shipping a test-only code path, and whether the cost is justified on the Linux runner only vs the full matrix.

Acceptance criteria

  • A documented local command that boots the app and drives one scenario end to end.
  • At least the Settings key-persistence scenario running in CI.
  • Reintroducing any of the four defects above turns the suite red.
  • If tauri-driver proves unworkable, the research outcome is recorded here and a narrower alternative is proposed rather than the issue being closed silently.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/ciCI pipeline, GitHub Actions, workflowsarea/frontendTouches apps/desktop frontend (React/Vite/Tailwind/ESLint)priority/highHigh-priority work — block other features until this landsstatus/needs-researchDeep multi-source research required before committing to an approachtype/choreRoutine maintenance / repo hygiene

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions