Mobile Testing
irahardianto/awesome-agv
Mobile E2E testing patterns — Flutter integrationtest, Patrol, Maestro, golden testing, device matrix, and test data management.
Run and debug Flutter E2E integration tests that exercise the real app against a local Docker backend (no mocks).
$ npx skills add divinevideo/divine-mobile --skill e2e-test -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install divinevideo/divine-mobile e2e-test --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/divinevideo/divine-mobile.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/e2e-test .claude/skills/e2e-test && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "e2e-test" agent skill from https://github.com/divinevideo/divine-mobile/tree/main/.agents/skills/e2e-test into .claude/skills/e2e-test/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "e2e-test", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/divinevideo/divine-mobile/tree/main/.agents/skills/e2e-testType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add divinevideo/divine-mobile --skill e2e-test -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install divinevideo/divine-mobile e2e-test --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/divinevideo/divine-mobile.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.agents/skills/e2e-test .agents/skills/e2e-test && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "e2e-test" agent skill from https://github.com/divinevideo/divine-mobile/tree/main/.agents/skills/e2e-test into .agents/skills/e2e-test/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "e2e-test", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add divinevideo/divine-mobile --skill e2e-test -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install divinevideo/divine-mobile e2e-test --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/divinevideo/divine-mobile.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.agents/skills/e2e-test .cursor/skills/e2e-test && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "e2e-test" agent skill from https://github.com/divinevideo/divine-mobile/tree/main/.agents/skills/e2e-test into .cursor/skills/e2e-test/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "e2e-test", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/divinevideo/divine-mobile.git --path .agents/skills/e2e-test--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add divinevideo/divine-mobile --skill e2e-test -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install divinevideo/divine-mobile e2e-test --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/divinevideo/divine-mobile.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.agents/skills/e2e-test .gemini/skills/e2e-test && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "e2e-test" agent skill from https://github.com/divinevideo/divine-mobile/tree/main/.agents/skills/e2e-test into .gemini/skills/e2e-test/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "e2e-test", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install divinevideo/divine-mobile e2e-testInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add divinevideo/divine-mobile --skill e2e-test -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/divinevideo/divine-mobile.git skills-src && mkdir -p .github/skills && cp -r skills-src/.agents/skills/e2e-test .github/skills/e2e-test && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "e2e-test" agent skill from https://github.com/divinevideo/divine-mobile/tree/main/.agents/skills/e2e-test into .github/skills/e2e-test/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "e2e-test", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add divinevideo/divine-mobile --skill e2e-test -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install divinevideo/divine-mobile e2e-test --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/divinevideo/divine-mobile.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.agents/skills/e2e-test .opencode/skills/e2e-test && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "e2e-test" agent skill from https://github.com/divinevideo/divine-mobile/tree/main/.agents/skills/e2e-test into .opencode/skills/e2e-test/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "e2e-test", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
e2e-testRun and debug Flutter E2E integration tests that exercise the real app against a local Docker backend (no mocks).
E2E Test is an agent skill from divinevideo/divine-mobile. Run and debug Flutter E2E integration tests that exercise the real app against a local Docker backend (no mocks). Use when running E2E tests, debugging failures, or working on the local harness.
Its SKILL.md is about 3.8k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Testing & QA, covering End-to-end testing, Integration testing and Cross-platform mobile apps. It works with Docker and Flutter. The licence is MPL-2.0.
Read from SKILL.md and the folder at commit 4c622be. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
miseflutterdockeradbbashrgdartFrom the folder's file list and the shell code blocks in SKILL.md.
Links to these hosts (documentation or services it may open):
patrol.leancode.coFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
E2E Test loads about 3.8k tokens when it runs. Until then it costs about 51 tokens; SKILL.md has 1,710 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check noted patterns worth knowing about, such as sudo or a known installer.
find it: sudo lsof -nP -iTCP:45173 -sTCP:LISTENAutomated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from divinevideo/divine-mobile at commit 4c622be, republished under its MPL-2.0 licence (© divinevideo). 1,710 words, ~3,751 tokens.
.claude/skills/e2e-test/SKILL.md (or your agent's skills folder).Goal: run the real app against a real local backend, end-to-end.
OAuth, relay subscriptions, and media uploads all hit local Docker
services — no mocks anywhere. Tests live in
mobile/integration_test/, backend in local_stack/.
Two terminals, from mobile/:
# Terminal 1 — emulator
mise run emulator
# Terminal 2 — tests
mise run e2e_test # All auth tests
mise run e2e_test integration_test/auth/auth_journey_test.dart # Single teste2e_test brings up the Docker stack, runs the suite, captures a
merged docker+logcat+app timeline at test_reports/*.jsonl, and
prints the native test XML path + failure excerpts when the APK
fails to install. For e2e targets, never call patrol test or
flutter test directly — you'll lose the timeline and the diagnostics.
Not every suite is a patrol suite. profile.sh recursively greps the
target for patrolTest and dispatches: patrol suites go to
patrol test, plain integration_test suites go to
flutter test --device-id. Everything under integration_test/e2e/
is now the plain kind. The original four converted off patrol in #7005 because
none used the native automator for anything load-bearing, and new suites should
follow that pattern. The plain path pre-grants POST_NOTIFICATIONS, since
without an automator nothing can dismiss that dialog.
patrol (the package) and patrol_cli (the binary) ship as a matched
pair, and patrol_cli enforces it at run time — a mismatch aborts the
run before any test executes.
| Half | Version | Declared in |
|---|---|---|
patrol package | 4.9.0 | mobile/pubspec.yaml (patrol: ">=4.9.0 <4.10.0") |
patrol_cli binary | 4.7.0 | local_stack/profile.sh (PATROL_CLI_VERSION) |
profile.sh checks the installed CLI and runs
dart pub global activate patrol_cli <version> when it differs, so
mise run e2e_test self-heals. That activation is machine-global:
it switches the CLI for every checkout, including worktrees still on an
older patrol, which will then fail the same compatibility check until
they rebase. Change the two versions together — the compatibility table
is at https://patrol.leancode.co/documentation/compatibility-table.
The package constraint pins a single minor rather than using a caret,
because that table closes open-ended bands retroactively. A caret range
lets flutter pub upgrade walk into a patrol the pinned CLI rejects,
and the abort then surfaces at patrol test time, unrelated to whatever
the upgrade was actually for.
| Service | Port | Purpose |
|---|---|---|
| Keycast | 43000 | OAuth + NIP-46 signer |
| FunnelCake Relay | 47777 | Nostr relay (WebSocket) |
| FunnelCake API | 47777 | REST API, under /api/ on the same proxy |
| Blossom | 43003 | Media server |
| Postgres | 15432 | Keycast DB |
The app reaches these at 10.0.2.2 from the emulator. Cleartext to
loopback hosts is permitted in every build type on both platforms.
Most services are irrelevant to any given test, and local_up
failing on one does not mean you are blocked. Check what is actually
healthy before debugging a service your flow never calls:
docker compose -f local_stack/docker-compose.yml psmise run local_up # Start (auto-runs local_setup on fresh worktrees)
mise run local_up_cached # Same, but reuse cached images (offline / rate-limited)
mise run local_down # Stop
mise run local_reset # Wipe data + restart
mise run local_status # HealthIf local_up fails only at e2e-seed and the services your test
actually needs are healthy (auth tests don't need the indexer),
bypass the seed:
bash ../local_stack/profile.sh integration_test/<your_test>.dartAny local_up failure prints the per-service status, the logs of
whatever is down, and that same bypass command. Set E2E_TEST_PATH
before the run and it prints the command for your test:
E2E_TEST_PATH=integration_test/auth/auth_journey_test.dart mise run local_upup.sh pre-flights every host port in docker-compose.yml before
starting anything. This machine runs several compose projects, and
stale test containers days old are the normal case, so collisions
are routine. The check names the service, the port, and the holder:
port 43000 wanted by service "keycast"
held by container "funnelcake-test-clickhouse-sim" — compose project "funnelcake-test"
remedy: docker rm -f funnelcake-test-clickhouse-sim
port 45173 wanted by service "keycast"
held by a host process (not a container), listening on: 127.0.0.1:45173
find it: sudo lsof -nP -iTCP:45173 -sTCP:LISTENPorts already published by our own containers are not conflicts —
up.sh is idempotent. The raw daemon error it replaces (Bind for 0.0.0.0:16380 failed: port is already allocated) named neither the
service nor the holder.
Listening sockets come from ss on Linux and lsof on macOS, and
the find it: line names whichever of the two the machine has. With
neither installed the run says so and falls back to container-held
ports alone, which docker ps reports without either tool — and a
stale container is the usual culprit anyway.
bash local_stack/test_stack_scripts.sh covers these paths against a
stubbed docker/ss/lsof, so it needs no daemon and no free ports.
Containers sometimes start before Docker's embedded DNS knows a
dependency's alias: funnelcake-migrate dies with dial tcp: lookup funnelcake-clickhouse on 127.0.0.11:53: no such host, or keycast
burns its DB connection attempts on Temporary failure in name resolution. Both succeed on an unchanged retry. up.sh re-runs the
whole up (idempotent — it restarts whatever died) up to 3 attempts,
5s apart, only when it sees a name-resolution signature in the
compose output or in the failed containers' logs. A port clash or a
bad image fails straight through rather than retrying pointlessly.
mise run emulator # Normal launch (auto-detects DISPLAY)
mise run emulator_headless # Offscreen, no window
mise run emulator_wipe # -wipe-data (storage exhausted)Override AVD: AVD_NAME=<name> mise run emulator. Always uses
-gpu host.
Debug builds render with Impeller, as release does. On an emulator the
engine picks Impeller OpenGLES, never Vulkan. If an emulator vanishes or
cannot render, e2e_test cannot pass a flag: it calls patrol test or
flutter test with fixed arguments, and Patrol launches the app without
intent extras. Build with the opt-out instead:
ORG_GRADLE_PROJECT_divineDisableImpeller=true mise run e2e_test ....
mobile/docs/ANDROID_LOCAL_SETUP.md ("Debug builds render with
Impeller") lists it with the flags for flutter run and adb.
Skip the per-run reinstall with PATROL_NO_UNINSTALL=true mise run e2e_test ... when iterating fast and the APK hasn't changed.
Stale-state debugging cost is yours.
Buffer auth-flow logs: adb logcat -G 16M (default 256 KB rotates
mid-flow).
Not just a Patrol problem — flutter run hits it too, and the error
is on the install, not the build:
java.io.IOException: Requested internal only, but not enough spaceA debug APK is ~289 MB and needs real headroom on top of that.
adb shell pm trim-caches 1G often does not free enough; mise run emulator_wipe (emulator.sh --wipe) is usually the faster fix.
pumpAndSettle hangs because of persistent polling timers — the app
polls email verification every 3s, so the tree never reaches a
quiescent frame and the call blocks until its 10-minute timeout. Use
launchAppGuarded (from test_setup.dart) and a bounded pump instead
of pumpAndSettle, and run the whole scenario inside
runWithAppErrorHandlers (see below):
await runWithAppErrorHandlers(() async {
launchAppGuarded(app.main);
await pumpUntilSettled(tester, maxSeconds: 3);
// ...the scenario...
drainAsyncErrors(tester);
});When you need to stop as soon as something appears rather than pump a
fixed budget, use waitForText / waitForWidget from
navigation_helpers.dart — both poll and return early.
The tell that a suite has this bug: patrol logs
PATROL_LOG {"type":"test",…,"status":"start"} and then no terminal
status at all, while the app keeps logging. It reads like a crash;
it is a hang.
runWithAppErrorHandlers is what lets a failed check fail the test.
app.main() replaces FlutterError.onError with a handler that does
not chain to flutter_test's, and flutter_test reports a failed expect
through whichever handler is current. Outside the helper the failure
never reaches the binding: the log shows the app's
Flutter Error: Expected: … line, then Failed assertion: … '_pendingExceptionDetails != null', and the run sits there until it is
killed (#9659). The helper puts the original handler back before the
failure propagates, suppresses known relay and teardown noise, and
restores ErrorWidget.builder, which flutter_test checks at the end of
the test body. check_integration_test_error_restore_safety.sh fails a
suite that imports main.dart without it.
UI navigates before publish/upload completes. Poll the relay:
for (var i = 0; i < 120; i++) {
await tester.pump(const Duration(milliseconds: 500));
events = await queryRelay(filter);
if (events.isNotEmpty) break;
}New bottom sheets may cover the target widget:
for (var i = 0; i < 20; i++) {
await tester.pump(const Duration(milliseconds: 250));
final gotIt = find.text('Got it!');
if (gotIt.evaluate().isNotEmpty) {
await tester.tap(gotIt);
break;
}
}A fresh install has no runtime permissions, and Android's permission
dialog sits in front of the app until it is answered. After sign-in the
app asks for notification permission; while that dialog is up, a bottom
sheet never finishes sliding in, so taps on its buttons miss or time
out. Patrol suites answer it with dismissNotificationPermission($)
before the step it would block, and call grantCameraAndMicrophone($)
before anything that records. Both match the dialog by its button id,
not by the text "Allow", which the notification dialog's title also
contains. Plain testWidgets suites cannot answer a native dialog, so
local_stack/profile.sh grants them the notification permission
before the run.
Patrol bundles every file in a target dir into one APK. When file B
runs, file A shows up as "not requested" [E] markers in logcat.
Trust only the final ✅/❌ lines.
/ or # in a patrol test namePatrol names each JUnit case MainActivityTest#runDartTest[<dart test name>], and the AndroidX orchestrator writes a per-test output file
named after it. Android's ContextImpl.makeFilename rejects any
filename containing a path separator, so a test called e.g. 'strips metadata via separate input/output paths' crashes the orchestrator:
FATAL EXCEPTION: AndroidTestOrchestrator
java.lang.IllegalArgumentException: File …input/output paths].txt
contains a path separatorThe tell is a green summary with a non-zero exit: Gradle reports
Instrumentation run failed due to Process crashed and exits 1, while
patrol prints Failed: 0 — because the offending test never started
and so was never counted. Compare Total: against the number of tests
in the file when the exit code disagrees with the summary.
A # crashes nothing, but the orchestrator reads it as the class/method
separator and cuts the JUnit id there, so tests whose names share the
text before it collapse into one entry in the test report. The three
Bug #2233 -- … tests in repro_log2_delete_test.dart reported as one.
Write input and output, not input/output, and Bug 2233, not
Bug #2233. test/integration_test_helpers/patrol_test_names_test.dart
fails CI when a group or patrolTest name in a Patrol suite contains
either character. It reads names from source, so it also fails a name
that is not a plain string literal: a variable, an interpolation, a raw
string or a concatenation.
Providers using requireIdentity (or similar non-nullable getters)
crash during cold start and Riverpod caches the error forever. Use
the nullable accessor (currentIdentity) and handle null.
TextField in an overlay/transition without Scaffold needs:
Material(color: Colors.transparent, child: TextField(...))integration_test/helpers/:
test_setup.dart — launchAppGuarded, error suppression, async-error drainnavigation_helpers.dart — register, login, tap tabs, wait for widgetsrelay_helpers.dart — publish/query Nostr eventsdb_helpers.dart — Postgres (verification tokens, refresh tokens)http_helpers.dart — Keycast API (verify email, forgot password)permission_helpers.dart — answer Android permission dialogs through Patrol (camera and microphone, notifications)constants.dart — ports + appPackagetail/headflutter run ... | tail -40 # WRONG
flutter run ... > /tmp/run.log 2>&1 # then read/grep the fileTwo separate failures. The pipe buffers until the command exits, so
you watch a blank screen and lose everything if you kill it. And the
pipeline's exit status is tail's, so a failed run reports success.
Redirect to a file and read that instead.
# Service logs
docker compose -f local_stack/docker-compose.yml logs keycast --tail=50
docker compose -f local_stack/docker-compose.yml logs blossom | grep -v 'path=/'
# Auth trace
adb logcat -d | grep 'flutter.*\[AUTH\]' | grep -v 'Router redirect'
# Last merged timeline
ls mobile/test_reports/*.jsonlThe timeline is where cross-service failures actually show up. A test can fail in teardown from an unhandled async error against a service that is down — Patrol's summary only says the test failed, while the timeline names the URL that was refused. Read it before writing a failure off as flaky.
rg -o '.{0,60}logout.{0,50}' mobile/test_reports/<run>.jsonlIf patrol reports Total: 0 with Gradle exit 1, the runner
auto-prints the native test XML path + failure excerpts — that's
an APK install failure, not a missing test. Free space with
adb shell pm trim-caches 1G or mise run emulator_wipe.
© divinevideo, MPL-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .agents/skills/e2e-test of divinevideo/divine-mobile.
Open the folder on GitHubat commit 4c622be
E2E Test next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| E2E Test this skilldivinevideo/divine-mobile | 266 | — | ~3.8k | Automated safety check: Notes | MPL-2.0 | |
| Mobile Testingirahardianto/awesome-agv | 157 | — | ~1.8k | Automated safety check: Notes | MIT | |
| Specialist Integration Test GeneratorHoangNguyen0403/agent-skills-standard | 571 | — | ~548 | Automated safety check: Pass | MIT | |
| MongoDB Source Connector E2E Harnessairbytehq/airbyte | 22k | — | ~1.9k | Automated safety check: Pass | Custom licence | |
| Go Redis Client Test Runnerredis/go-redis | 22k | — | ~786 | Automated safety check: Pass | BSD-2-Clause | |
| Airbyte Postgres Source E2E Testsairbytehq/airbyte | 22k | — | ~2.5k | Automated safety check: Pass | Custom licence |
irahardianto/awesome-agv
Mobile E2E testing patterns — Flutter integrationtest, Patrol, Maestro, golden testing, device matrix, and test data management.
HoangNguyen0403/agent-skills-standard
Generates one integration/E2E test from an approved test case spec using existing project patterns.
airbytehq/airbyte
Starts a throwaway MongoDB 7.0 replica set and runs the Airbyte spec, check, discover and read commands against source-mongodb-v2 images for local end-to-end testing.
redis/go-redis
Explains how to run go-redis tests: the Docker Compose stack, make targets, focusing a single Ginkgo spec, the e2e suite and the version environment variables.
airbytehq/airbyte
Starts a local PostgreSQL 16 container, loads SQL fixtures and runs the Airbyte spec, check, discover and read commands against a chosen source-postgres image.
airbytehq/airbyte
Reproduces PostgreSQL logical-decoding CDC behavior for Airbyte's source-postgres connector on a local backend, with CDC fixtures, a catalog and smoke case scripts.
divinevideo/divine-mobile
Fix ArgoCD ExternalSecret deployment failing with "namespace X is not permitted in project Y".
divinevideo/divine-mobile
Art direction for any content — reads text, PDF, Word, HTML, PPT, then proposes 2-3 creative directions with photography style, mood, and visual language.
divinevideo/divine-mobile
Fix "Null check operator used on a null value" errors when an object is set to null during an async await.
divinevideo/divine-mobile
Add custom metadata headers (x-amz-meta-) to AWS v4 signed requests for GCS S3-compatible API.
divinevideo/divine-mobile
Fix password/secret authentication failures caused by trailing newlines when creating Google Cloud secrets (or similar) with bash here-strings.
divinevideo/divine-mobile
Fix silent video/media processing failures caused by URL extraction code that filters on file extensions (.mp4, .webm, .webp).
Categories
Run and debug Flutter E2E integration tests that exercise the real app against a local Docker backend (no mocks). E2E Test is an agent skill from divinevideo/divine-mobile. Run and debug Flutter E2E integration tests that exercise the real app against a local Docker backend (no mocks).
E2E Test fits situations like: running E2E tests; debugging failures; working on the local harness.
Run `npx skills add divinevideo/divine-mobile --skill e2e-test -a claude-code`. Or copy the skill folder (.agents/skills/e2e-test in divinevideo/divine-mobile) into .claude/skills/e2e-test in your project. Claude Code loads it when a task matches its description.
Run `npx skills add divinevideo/divine-mobile --skill e2e-test -a codex`. Or copy the skill folder (.agents/skills/e2e-test in divinevideo/divine-mobile) into .agents/skills/e2e-test in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add divinevideo/divine-mobile --skill e2e-test -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/e2e-test, .gemini/skills/e2e-test, .github/skills/e2e-test and .opencode/skills/e2e-test in your project.
Going by SKILL.md and its folder, E2E Test needs the command-line tools its instructions call (mise, flutter, docker, adb, bash and rg). Our summary lists: Docker.
SKILL.md names 1 domain. As links in the text: patrol.leancode.co. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found notes only (runs commands with sudo), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.
E2E Test is published under the MPL-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 3.8k tokens (SKILL.md is roughly 15k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with E2E Test: Mobile Testing (irahardianto/awesome-agv, 157 stars), Specialist Integration Test Generator (HoangNguyen0403/agent-skills-standard, 571 stars), MongoDB Source Connector E2E Harness (airbytehq/airbyte, 22k stars) and Go Redis Client Test Runner (redis/go-redis, 22k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
divinevideo (a GitHub organization) maintains it in divinevideo/divine-mobile, which has 266 GitHub stars. The repository holds 103 skills in this directory. The repository was last updated on October 8, 2026.
Source: divinevideo/divine-mobile on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.