Skip to content

CI: Comprehensive UI screenshot walkthrough with data seeding#59

Merged
ketansp merged 4 commits into
masterfrom
claude/android-ui-screenshot-coverage-0827cc
Jun 30, 2026
Merged

CI: Comprehensive UI screenshot walkthrough with data seeding#59
ketansp merged 4 commits into
masterfrom
claude/android-ui-screenshot-coverage-0827cc

Conversation

@ketansp

@ketansp ketansp commented Jun 28, 2026

Copy link
Copy Markdown
Owner

Summary

Overhaul the Android UI screenshot CI pipeline to capture a complete, data-driven walkthrough of every screen, sub-menu, and theme variation. The new approach pre-seeds realistic data (home apps, notes history with mixed media) directly into the app's storage, then drives the full UI with resolution-independent gesture automation, producing a gallery that doubles as verification testing.

Key Changes

  • Enhanced ui_screenshots.sh: Expanded from a basic 5-screen walkthrough to a comprehensive 24-screenshot gallery covering:

    • Home screen (dark theme, right-aligned)
    • App drawer with live search and per-app action menu
    • Full Settings hierarchy (home layout, appearance, DND, gestures)
    • Notes with text, to-dos, reminders, image viewer, and search
    • Theme/layout variations (light theme, center alignment, empty states)
  • New seed_data.py: Generates pre-seeded SharedPreferences XML files:

    • Main prefs: home apps (curated from actually-installed packages), layout settings, theme, gestures, DND config, and onboarding flags disabled
    • Notes prefs: realistic chat-like history with 8–9 notes (text, done to-do, urgent reminder, image, voice memo) timestamped over the past ~2 hours
  • New find_node.py: UIAutomator-based node locator for resolution-independent taps:

    • Parses uiautomator dump XML to find nodes by text, content-desc, resource-id, or class
    • Supports substring matching, clickability filtering, and index selection
    • Returns center coordinates for accurate, layout-agnostic gesture automation
  • Gesture automation improvements:

    • New tap() and longpress() helpers that locate elements via UIAutomator before tapping
    • scroll_to_text() for navigating long settings pages
    • type_text() for search input
    • Removed set -e to allow best-effort walkthrough (one failed tap doesn't abort the gallery)
  • Data seeding workflow:

    • Discovers launchable packages on the emulator and selects 6 curated home apps from what's actually installed
    • Generates a sample gradient image (via ImageMagick) for the image note
    • Writes all seed data via adb shell run-as to respect app security context
    • Flips first-run flags so no onboarding dialogs hide the UI
  • Manifest format: Updated from 2-column to 3-column TSV (filename | section | caption) to group screenshots by feature area in the published gallery

  • Workflow updates (android-ui-screenshots.yml):

    • Added PR trigger so the gallery appears on pull requests during review
    • Updated job description to clarify data seeding and verification testing role
    • Improved comments explaining the multi-step process
  • Gallery publishing (publish_screenshots.sh):

    • Grouped screenshots by section (Home screen, App drawer, Settings, Notes, Variations)
    • Added screenshot count to the summary header
    • Improved markdown formatting with captions and section headers

Implementation Details

  • No hard-coded coordinates: All taps use UIAutomator node lookup, making the walkthrough robust across screen sizes and layout changes
  • Realistic data: Home apps are validated against the emulator's installed packages; notes include a mix of types (text, to-do, reminder, image, audio) with realistic timestamps
  • Best-effort walkthrough: Missing UI elements log warnings but don't abort, so the gallery captures as much as possible even if one step fails
  • Demo mode: Configures a clean status bar (clock, battery, network) for consistent screenshots
  • Security: All seed data written via adb shell run-as to preserve app ownership and SELinux labels

The gallery now serves dual purpose: a visual showcase of every feature and a regression test that verifies the UI renders correctly with data.

https://claude.ai/code/session_01PTbv7mVssh3FXvhdVAMnzN

claude added 4 commits June 28, 2026 18:55
Turn the Android UI Screenshot workflow into a verification gallery of every
screen in the app, each shown with realistic data.

- Pre-seed the app's SharedPreferences before launch (via run-as, SELinux-safe):
  a curated set of home apps picked from packages actually installed on the
  emulator, and a rich notes history (text, a done to-do, an urgent reminder,
  an image and a voice memo). First-run flags are flipped off so no onboarding
  dialog hides the UI. seed_data.py builds both prefs XML files; find_node.py
  lets the driver tap real on-screen elements located from a live
  `uiautomator dump` instead of hard-coded coordinates.

- Walk and screenshot 24 states across Home, App drawer (list, live search,
  per-app long-press menu, inline rename), Settings (home/appearance/DND/
  gestures sections plus their sub-selectors), Notes (list, actions menu,
  inline edit, full-screen image, search, empty state), and a couple of
  live theme/alignment variations.

- Publish step renders the gallery into the run's Job Summary grouped by
  section (images embed inline via the ci-screenshots branch).

- Also run on PRs into main/master so the gallery shows up during review;
  bump the job timeout to 60m for the longer walkthrough.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PTbv7mVssh3FXvhdVAMnzN
The first run of the walkthrough captured the home screen for nearly every
step. Three root causes, all fixed here:

1. Seeding silently failed. `adb shell run-as PKG sh -c 'cat > file'` has adb
   flatten argv into one string, so the device shell (uid shell, cwd /) ran the
   `>` redirect instead of the app-context sh — "No such file or directory", and
   nothing got seeded. The app ran in first-run state with default apps and no
   notes. Fixed by passing the whole run-as invocation as one double-quoted arg
   (new appwrite/appwrite_b64 helpers) so the redirect stays inside the single
   quotes and runs in the app's data dir.

2. Navigation never happened. `input swipe … 120ms` wasn't detected as a fling,
   so swipe-up/left didn't open the drawer/notes (long-press worked, hence
   Settings did). Replaced with open_drawer/open_notes that swipe and then
   verify via uiautomator, retrying across several durations.

3. Variation + option taps hit off-screen targets. Inline selectors render below
   low settings rows; reveal_row now scrolls the row up first, and the home
   theme/alignment variations are produced by re-seeding prefs and restarting
   (seed_main) instead of driving the off-screen selectors.

seed_data.py gains optional theme/alignment/apps-count overrides for the
re-seeded variation screenshots.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PTbv7mVssh3FXvhdVAMnzN
… drawer

Seeding works now, but reviewing the captured images showed the walkthrough
still misfired in several places. Root causes and fixes:

- Notes section (every shot was actually the home screen): swipe-left never
  fires onSwipeLeft on this emulator. Open the Notes page deterministically via
  MainActivity's ACTION_SEND handler (`am start -a SEND -t text/plain`), which
  drops shared text onto the notes page and navigates there — no gesture.

- App search launched Google Calendar instead of filtering: AppDrawerAdapter
  auto-launches when the query narrows to exactly one app. Search "c" (matches
  several) instead of "ca" (only Calendar).

- Settings pickers never expanded: each row's click handler is on the *value*
  view (homeAppsNum, dateTime, iconShape, alignment, appThemeText, dndDuration,
  swipeLeftAction, tvGestures), not the label I was tapping. New expand_setting
  taps the value id; find_node now prefers exact id matches (so "alignment"
  doesn't hit "alignmentLeft").

- Drawer menu/rename shots were home: the drawer didn't reopen after the search
  excursion. Restart fresh before reopening (a cold launch is the one state
  where the swipe-up fling reliably registers).

- Home slot 4 showed "App": com.android.camera2 has no launchable activity
  under -camera-back none. Dropped Camera from the preferred home apps.

- Image shot opened the notification shade: the reveal swipe was a home
  swipe-down; scroll within the notes list instead.

Also drop the notes empty-state shot (couldn't be reached without the broken
swipe) and add diag() logging on navigation misses.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PTbv7mVssh3FXvhdVAMnzN
…ImageMagick

Viewing run #3: home, drawer, search, all Settings pickers, the notes list, notes
search and both variations now render correctly. Three things still misfired:

- App-menu/rename shots were the home screen: the swipe-up fling won't register
  after a restart, so reopening the drawer failed. open_drawer now falls back to
  long-pressing a home app (onLongClick -> showAppList), which opens the same
  searchable app list reliably and without the single-match auto-launch.

- Note action dialog never opened (long-press selected the note text instead):
  notesText is textIsSelectable while the row's long-click is on the root view.
  New longpress_note presses the row gap just right of the bubble (find_node
  gained --bounds) so the root long-click fires -> Copy/Share/Edit/Delete.

- Image note was missing ("9 entries", no thumbnail): the runner has no
  ImageMagick, so the sample PNG was never created and the image entry was
  skipped. Generate it with pure-stdlib Python (make_png.py) and log the pushed
  size to confirm it lands.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PTbv7mVssh3FXvhdVAMnzN
@ketansp ketansp merged commit 4698504 into master Jun 30, 2026
1 check passed
@ketansp ketansp deleted the claude/android-ui-screenshot-coverage-0827cc branch June 30, 2026 14:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants