Files
Gotcha/TESTING.md
2026-08-01 15:48:14 +02:00

358 lines
20 KiB
Markdown

# 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.
- [ ] On accounts/repositories with more than 30 results, Home activity,
repositories, issues, pull requests, milestones, milestone contents,
commit history, and pull-request files initially show one page plus a
**Pull up or tap to load more**
footer. Pull upward past the bottom and verify the footer changes to a
native loading indicator, the next page appends without duplicates, and
the footer disappears after the final page.
- [ ] Tap the load-more footer as an accessibility alternative and repeat while
VoiceOver is running. It announces loading, ignores repeated activation
while a request is active, preserves the current scroll position, and
allows retry after an error.
- [ ] Pull down to refresh after loading multiple pages. The content resets to
the new first page, filtering/branch changes also reset pagination, and
switching History/Files never shows a stale load-more footer.
- [ ] 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.
- [ ] The nine-month activity strip is horizontally centered beneath its title
without clipping either edge.
- [ ] 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 without requiring a manual pull-up; the empty
state appears only after every available page has been checked.
- [ ] 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 but
does not change the same repository's favorite in Repos or Milestones.
- [ ] Open a repository; the issue list defaults to the saved Open/Closed filter.
- [ ] Repository issue rows and issue rows inside a milestone show a green open
or purple closed icon beside the title; mixed milestone results use the
correct icon per row and VoiceOver announces each state.
- [ ] Change the native filter menu between Open and Closed; the checkmark,
rows, and persisted selection update.
- [ ] Select one and then multiple labels in the issue filter. Checkmarks and
rows update without dismissing the menu; clearing every label restores
the unfiltered label result.
- [ ] Open **Search Text** in the issue filter, enter a term, and verify the
server-filtered rows and menu subtitle update. Combine it with Closed and
one or more labels and verify every filter applies together.
- [ ] Select a milestone and then All Milestones; the checkmark and issue rows
update. Relaunch and revisit repositories to verify label and milestone
selections persist independently per repository and status persists.
- [ ] The issue-filter icon uses a neutral color for Open + All Milestones + no
labels, and the app accent color whenever any non-default filter is set.
- [ ] In the issue filter panel, the Search Text, Status, Milestone, and Labels
icons use the app accent color independently when their filter is
non-default. Search text remains while navigating during the current app
session but is empty after relaunch. **Clear Filters** restores empty
search + Open + All Milestones + no labels, refreshes the rows, and
returns every filter icon to neutral.
- [ ] Tap the add button. **New Issue** appears as a native modal with Cancel
and Save, title and Markdown body fields, multi-select labels, a
single-select optional milestone, a **Closed** switch that defaults off,
and an optional inline due-date picker.
- [ ] In the new-issue body, enter headings, emphasis, a list, a link, and a
fenced code block. **Write** syntax-highlights the Markdown and **Preview**
renders it; switching repeatedly preserves the exact source text.
- [ ] Save is disabled for an empty or whitespace-only title. Create issues with
no labels/milestone/due date and with multiple labels, a milestone, and a
due date; each new issue appears in the list and opens its detail.
- [ ] Tap the pencil button on an issue. Change its title and Markdown body, replace and
clear labels, select and clear its milestone, and add, change, and remove
its due date. Turn **Closed** on and save, then edit it again and turn
**Closed** off. Save, refresh, and relaunch to verify every change persists.
- [ ] In the issue list, partially swipe an open issue to reveal **Close** and
**Delete**. Cancel the destructive Delete confirmation and verify nothing
changes. Full-swipe the same row to close it, switch to Closed issues, and
full-swipe it again to reopen it; each row leaves the current filtered list
only after the server mutation succeeds.
- [ ] Cancel both new and edited issues, including with the keyboard and date
picker visible. Nothing is saved, the modal dismisses normally, and the
issue list/detail remains usable with Dynamic Type and VoiceOver labels.
- [ ] Open both an open and a closed issue. A green open or purple closed icon
appears beside the title and VoiceOver announces the state; author
metadata, every colored label, Markdown body, and comments remain correct.
Multiple labels wrap without clipping at large Dynamic Type sizes and
VoiceOver announces each label. Links and selectable text use normal iOS
interaction.
- [ ] Open issue #50 and verify its body renders separate paragraphs and a
two-item unordered list. Add or edit a comment containing two paragraphs,
an unordered list, emphasis, and a link; verify every Markdown block and
inline style renders correctly after saving and after pull-to-refresh.
- [ ] Tap the **Add comment** icon on an issue. Enter headings, emphasis, a
list, link, and fenced code block; **Write** syntax-highlights the
Markdown, **Preview** renders it, and switching modes preserves the exact
source. Save and verify the rendered comment appears after the detail
refresh; Cancel leaves the issue unchanged.
- [ ] Each comment authored by the signed-in account has its own pencil button
and comments by other accounts do not. Edit an owned comment in
Write and Preview modes, save it, refresh and relaunch, and verify the
Markdown change persists. Check Add/Edit/Cancel/Save with Dynamic Type
and VoiceOver, including the empty-comment Save state.
## Repositories and commits
- [ ] The repository list and favorite behavior match the Issues tab. Toggle a
favorite and confirm it persists without affecting Issues or Milestones.
- [ ] 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 align with their rows while scrolling; branch-out and
merge-back connections use smooth, rounded curves that meet the correct
lane and commit node without angular horizontal bars or overlaps.
- [ ] In **All** history, branch names use the accent color both at branch tips
and at the first commit made on a pull-request branch, including a merged
branch whose tip was deleted.
- [ ] Open a commit and verify its header shows the full title and description,
full hash, author, committer, date, known branch/ref, and signature status
above the Changed Files paths and statuses. Unsigned commits say
**Unsigned**. Verify paragraphs, lists, links, and inline styles in a
multi-line commit description use the repository file Preview Markdown
presentation. Check that long values wrap and remain readable at the
largest Dynamic Type accessibility size.
- [ ] Open a changed file and verify the diff title, old/new line numbers,
monospaced text, addition/removal/hunk colors, vertical scrolling, and
source-style horizontal scrolling for long lines without word wrapping,
clipped or jumping text, or content hidden beneath the navigation bar.
- [ ] 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.
- [ ] In the repository root and in several nested folders, switch between
**Files** and **History**. Each folder history contains only commits that
affect that folder or its descendants. Switch back to Files and verify the
same folder and navigation stack are preserved. Open a history commit and
verify its changed-files detail opens normally.
- [ ] 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, its first line starts below the navigation bar, and 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.
- [ ] Switch Markdown files among **Preview**, **Source**, and **History** and
switch other source and native-preview files between **Content** and
**History**. Each history contains only commits that affect that exact
file. Returning to content preserves the file path and restores its native
preview or source presentation without stale or overlapping views.
- [ ] 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.
- [ ] Open **Search Text** in the pull-request filter, enter a term, and verify
the server-filtered rows and menu subtitle update. Combine it with Closed
and a milestone and verify every filter applies together.
- [ ] Select a milestone and then All Milestones; the checkmark and pull-request
rows update, and the milestone selection persists independently per
server after relaunch.
- [ ] The pull-request filter icon uses a neutral color for Open + All
Milestones and the app accent color whenever either filter is non-default.
- [ ] In the pull-request filter panel, Search Text, Status, and Milestone icons
use the app accent color independently when non-default. Search text
remains while navigating during the current app session but is empty
after relaunch. **Clear Filters** restores empty search + Open + All
Milestones, refreshes the rows, and returns every icon to neutral.
- [ ] Each row shows repository/number, title, author/update metadata, comment
count, and draft/merged state where applicable. Open rows show a green
icon, closed rows show a purple icon, and VoiceOver announces the state.
- [ ] Open a pull request and verify title, metadata, Markdown body, comments,
changed-file reference, and matching open/closed state icon with a
VoiceOver state announcement. Its file paths, statuses, left alignment,
separators, and disclosure indicators match the commit changed-file list.
- [ ] 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.
- [ ] Toggle a repository favorite and confirm it persists after refresh and
relaunch without affecting the same repository in Issues or Repos.
- [ ] Each milestone shows its title, description, state, due date, issue
counts, and a green/amber closed/open progress bar. Lists and details show
a green open or purple closed icon and VoiceOver announces the state.
- [ ] A milestone description containing multiple paragraphs, a list, emphasis,
and a link uses the repository file Preview Markdown presentation in both
the milestone list and detail.
- [ ] Open a milestone and verify every assigned issue and pull request is
listed; tapping either opens its normal detail.
- [ ] Tap the add button. **New Milestone** has native Cancel and Save controls,
title and multiline description fields, a **Closed** switch that defaults
off, and an optional inline date picker. Save is disabled for an empty or
whitespace-only title. Create milestones both without and with a due date
and verify each appears open.
- [ ] Tap the pencil button on a milestone. Change its title and description, add and
change its due date, then turn Due Date off and save to clear it. Turn
**Closed** on and save; verify the list and detail show the closed state.
Edit it again, turn **Closed** off, and verify it reopens. Refresh and
relaunch after each save to verify persistence; Cancel leaves every value
unchanged. Exercise the form with the keyboard, Dynamic Type, and
VoiceOver labels.
- [ ] 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.