# Testing Gotcha

This document is the source of truth for iOS visual verification. Every UI
change must update its relevant scenarios in the same commit. For ordinary
commits, run the build gates and every scenario affected by the change. A
release test means completing this entire checklist successfully on the stated
simulators and devices; record failures as open issues and do not sign off until
every scenario passes.

## Test record

- Release/build:
- Commit:
- Date and tester:
- Xcode and iOS versions:
- Simulator/device:
- Gitea server version:
- Result and open issues:

Use a real test account with repositories, open and closed issues, open and
closed pull requests, multiple branches, commits, comments, and file changes.
Never paste a production token into logs, screenshots, source files, or this
document. The app stores entered tokens in the Apple Keychain.

Run both of these passes:

- Fresh install on a disposable simulator, including Add Server.
- Upgrade/reinstall over the previous build, preserving app data and Keychain.

## Build gates

From the repository root, all commands must pass without warnings:

```sh
cargo fmt --all -- --check
RUSTFLAGS="-D warnings" cargo check --workspace --all-targets
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
```

Build and install the simulator app:

```sh
cd ios
xcodegen generate

xcodebuild \
  -project Gotcha.xcodeproj \
  -scheme Gotcha \
  -configuration Debug \
  -sdk iphonesimulator \
  -destination 'platform=iOS Simulator,name=iPhone 17 Pro' \
  ARCHS=arm64 \
  ONLY_ACTIVE_ARCH=YES \
  build

gotcha_build_dir="$(
  xcodebuild \
    -project Gotcha.xcodeproj \
    -scheme Gotcha \
    -configuration Debug \
    -sdk iphonesimulator \
    -destination 'platform=iOS Simulator,name=iPhone 17 Pro' \
    -showBuildSettings -json \
    ARCHS=arm64 \
    ONLY_ACTIVE_ARCH=YES |
  plutil -extract 0.buildSettings.TARGET_BUILD_DIR raw -o - -
)"
xcrun simctl install booted "$gotcha_build_dir/Gotcha.app"
xcrun simctl launch booted de.rfc1437.gotcha
```

## Add Server and native text editing

- [ ] With no configured server, Issues and Repos show the Servers screen and
      its empty state.
- [ ] The add button presents Add Server; Cancel dismisses it.
- [ ] Name, Server URL, and Access token use native text fields and suitable
      keyboards; Next advances between fields and Done submits.
- [ ] Long-press in every field shows the native loupe, insertion point, and
      selection handles.
- [ ] The standard edit menu offers Cut, Copy, Paste, Select, and Select All as
      applicable. There is no app-specific editing toolbar.
- [ ] Copy text from one field and paste it into another; verify the exact text.
- [ ] The token is obscured, remains editable, and does not trigger a password
      save prompt.
- [ ] Empty or invalid values show an error without adding a server.
- [ ] Valid credentials add and select the server; all data tabs load.
- [ ] Terminate and relaunch the app; the selected server and Keychain token
      still work without re-entry.
- [ ] Open the server picker from a repository list and switch between at least
      two configured servers; every data tab changes to the selected server.

## Native interaction and navigation

- [ ] Every list scrolls with normal drag, momentum, bounce, and scroll-bar
      behavior. Rows are flat, use system separators, and have no card-shaped
      rounded backgrounds.
- [ ] Pull past the top of Home, repository lists, issue lists, pull lists,
      commit history, changed files, issue details, pull details, and diffs.
      The native refresh control appears, reloads data, and disappears.
- [ ] Tap a row, scroll its detail, and use both the navigation-bar Back button
      and the left-edge interactive swipe to return.
- [ ] From a list scrolled well away from the top, open a detail and go Back.
      The same rows and scroll offset remain visible.
- [ ] Switch tabs while a tab has a pushed detail and a scrolled list; returning
      to the tab preserves its navigation stack and position.
- [ ] Rapidly change tabs, filters, and branches while content loads. The app
      neither crashes nor replaces a newer result with a cancelled request.
- [ ] Loading and error states remain dismissible and do not leave a refresh
      indicator or navigation-bar spinner running.

## Home

- [ ] Home shows the selected server name, contribution total, nine labeled
      months with gaps between them, and recent activity.
- [ ] Activity rows have the correct icon, repository, summary, and date.
- [ ] The compact icon row below the activity graph sits flat on the normal
      background with no border or pill and defaults to the clock. Select the
      issue and pull-request icons in turn; each shows only matching recent
      activity or the native empty state, then the clock restores all rows.
- [ ] Pull-request activity includes older creation and close events beyond the
      first activity-feed page.
- [ ] Tap repository, issue, pull-request, and commit activity. Each opens the
      matching native tab and destination.
- [ ] Non-linkable server activity does not navigate or appear tappable.

## Issues

- [ ] The repository list shows name, description, language, open count, update
      date, and current favorite state.
- [ ] Toggle a favorite and confirm it remains after refresh and relaunch.
- [ ] Open a repository; the issue list defaults to the saved Open/Closed filter.
- [ ] Change the native filter menu between Open and Closed; the checkmark,
      rows, and persisted selection update.
- [ ] Open an issue and verify title, state/author metadata, Markdown body, and
      comments. Links and selectable text use normal iOS interaction.

## Repositories and commits

- [ ] The repository list and favorite behavior match the Issues tab.
- [ ] Open a repository; commit history initially selects **All**, visibly shows
      All in the navigation bar, and includes commits from multiple branches.
- [ ] Open the branch menu; All is checked. Select a branch and verify the label,
      checkmark, commits, and graph update, then return to All.
- [ ] Commit graph lanes and merge connections align with their rows while
      scrolling.
- [ ] Open a commit and verify Changed Files paths and statuses.
- [ ] Open a changed file and verify the diff title, old/new line numbers,
      monospaced text, addition/removal/hunk colors, vertical scrolling, and
      horizontal scrolling for long lines.
- [ ] Long-press diff text and verify normal selection and copying.

## Repository files

- [ ] Switch a repository between **History** and **Files**. Each mode displays
      the expected content and switching back preserves normal navigation.
- [ ] In Files, traverse several nested folders using rows, the navigation-bar
      Back button, and the left-edge swipe. Folder contents and titles match the
      repository hierarchy.
- [ ] Open representative source files in several languages, including Rust,
      Swift, and a scripting or markup language. Keywords, strings, comments,
      types, and punctuation use plausible language-specific highlighting.
- [ ] Open a source file containing a line wider than the screen. It does not
      word-wrap; horizontal dragging pans smoothly across the complete line
      without blank, black, clipped, delayed, or jumping text. Vertical
      scrolling, selection, and copying still work.
- [ ] Open Markdown files using the supported extensions (`.md`, `.markdown`,
      `.mdown`, and `.mkd`). **Preview** is selected by default and renders
      headings, paragraphs, emphasis, links, lists, task lists, blockquotes,
      fenced code blocks, tables, and thematic rules as structured content.
- [ ] Switch a Markdown file from **Preview** to **Source**. The literal Markdown
      is syntax-highlighted, selectable, does not word-wrap, and scrolls
      horizontally for long lines. Switch back and verify the rendered preview
      is restored without stale or overlapping content.
- [ ] Open representative image, PDF, audio, and video files. Each uses the
      native preview appropriate to its media type and returns cleanly to Files.

## Pull requests

- [ ] The list defaults to the saved Open/Closed filter.
- [ ] Change the native filter menu between Open and Closed; the checkmark,
      rows, and persisted selection update.
- [ ] Each row shows repository/number, title, author/update metadata, comment
      count, and draft/merged state where applicable.
- [ ] Open a pull request and verify title, metadata, Markdown body, comments,
      changed-file reference, file paths, and statuses.
- [ ] Open a changed file and run the same diff checks as for a commit.

## Milestones

- [ ] Milestones uses the server → repository → milestone flow and includes
      both open and closed milestones.
- [ ] Each milestone shows its title, description, state, due date, issue
      counts, and a green/amber closed/open progress bar.
- [ ] Open a milestone and verify every assigned issue is listed; tapping an
      issue opens its normal issue detail.
- [ ] Repository issue lists and issue details show the assigned milestone with
      a flag icon instead of a text label.
- [ ] Repositories without milestones show the native empty state.

## Settings, accessibility, and lifecycle

- [ ] Settings opens from the gear button on Home and is not a tab.
- [ ] Appearance changes between Auto, Light, and Dark immediately; Auto follows
      the simulator system appearance.
- [ ] Icon and appearance settings remain selected after relaunch.
- [ ] Test Light and Dark appearances for readable text, separators, graph lines,
      diff colors, menus, selection, loading, empty, and error states.
- [ ] Test at the default and at least one larger Dynamic Type size. Text remains
      readable without hiding required controls.
- [ ] VoiceOver announces tabs, navigation controls, filters, favorites, rows,
      fields, and changed-file statuses meaningfully and in a usable order.
- [ ] Rotate, background/foreground, terminate/relaunch, and temporarily disable
      networking. The app recovers without losing preferences or credentials.

## Release sign-off

- [ ] All build gates passed.
- [ ] Fresh-install and upgrade passes completed.
- [ ] Every supported iOS version and required device class completed.
- [ ] Every scenario passed; any discovered failures were resolved and retested.
