Skip to content

Conversation

@k9ert
Copy link
Contributor

@k9ert k9ert commented Dec 17, 2025

Summary

  • MCP server for app automation via Appium
  • TypeScript CLI for shell-based interaction
  • Service orchestration (emulator, Metro, Appium, app)
  • Agent guide documentation

Commits

  • feat: mcp server
  • feat: mcp server done right
  • feat(mcp): CLI, agent guide, tool improvements
  • chore: add appium dependency

Screenshot

Screenshot 2025-12-16 at 18 35 20

🤖 Generated with Claude Code


Appendix: Design Decisions

Why not mobile-mcp?

mobile-mcp is an alternative MCP server for mobile automation. After research, here's why we built a custom Appium-based solution:

What mobile-mcp uses under the hood:

  • @mobilenext/mobilecli - wraps raw ADB commands and xcrun simctl
  • Direct coordinate-based taps from accessibility snapshots
  • No WebDriver protocol

Limitations for Blink's use case:

Feature mobile-mcp Our Appium implementation
Element waiting Manual retry loops needed waitForDisplayed with configurable timeout
Element finding Coordinate-based (fragile across screen sizes) WebDriver selectors (~testID, XPath)
React Native testID Via accessibility snapshot parsing Native ~id selector (W3C standard)
Hot reload Not supported Dev menu access via mobile: shell
Shell commands Not exposed Full ADB shell access
Session management Stateless CLI calls Persistent WebDriver session with element caching
Ecosystem New, limited docs Battle-tested, extensive documentation

Key risk with mobile-mcp: Coordinate-based taps break when:

  • Screen density differs between devices
  • UI layouts change slightly
  • Animations shift element positions

Our WebDriver approach finds elements by accessibility ID regardless of position, making tests more resilient.

Why Appium instead of BrowserStack/cloud solutions?

BrowserStack and similar cloud services offer real device farms with parallel testing. However:

Why local Appium is better for our use case:

  1. Development workflow: We need fast iteration on a local emulator (~35s cold boot). Cloud round-trips add latency.

  2. Cost: Cloud device farms charge per minute. Development sessions can run hours.

  3. MCP integration: Local Appium allows direct stdio MCP transport. Cloud would require additional networking/auth complexity.

  4. Simplicity: Single-developer workflow doesn't need distributed device management.

What BrowserStack adds (that we don't need yet):

  • Real device coverage across hundreds of models
  • Parallel test execution across device matrix
  • AI-driven test healing and flake detection
  • Video recording and network logs

When to consider cloud: If/when we need CI testing across multiple real devices, BrowserStack/AWS Device Farm integration would make sense. The Appium tests we write locally would work unchanged on cloud infrastructure.

Why Appium specifically?

Appium's UiAutomator2 driver provides capabilities beyond basic ADB:

  • W3C WebDriver protocol: Standard API, works with any WebDriver client
  • Element strategies: Find by accessibility ID, XPath, class, text
  • Automatic waiting: Built-in element polling with timeouts
  • App lifecycle: Install, launch, terminate, activate apps
  • Advanced features: Clipboard access, geolocation mocking, performance data, network monitoring

Our implementation currently uses a subset (element finding, tapping, typing, screenshots) but can expand to use these advanced features as needed.

Sources

k9ert and others added 4 commits December 16, 2025 19:16
- Add TypeScript CLI (cli.ts) for shell-based app interaction
- Add AGENT_GUIDE.md with comprehensive MCP tooling docs
- getScreen now returns {testIds, tree} for easier element discovery
- Add startServices MCP tool to launch infrastructure
- Refactor state to .mcp/ dir (logs/, pids/, ready)
- Update .gitignore for .mcp/ and .beads/

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings December 17, 2025 11:03
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request adds comprehensive MCP (Model Context Protocol) server infrastructure for automated mobile app testing via Appium, enabling AI agents to interact with the Blink React Native app.

Key Changes:

  • Added Appium as a development dependency for mobile automation
  • Implemented TypeScript MCP server with 11 tools for app interaction (tap, type, swipe, getScreen, etc.)
  • Created shell-based orchestration system for managing emulator, Metro, Appium, and app lifecycle
  • Added TypeScript CLI tool for manual app interaction
  • Comprehensive agent documentation guide (376 lines)

Reviewed changes

Copilot reviewed 38 out of 41 changed files in this pull request and generated 16 comments.

Show a summary per file
File Description
package.json Added appium ^3.1.2 as devDependency
yarn.lock Added Appium and 133+ transitive dependencies
dev/mcp-server/src/* TypeScript MCP server implementation (tools, client, parsers)
dev/mcp/orchestrator.sh Main service orchestration script
dev/mcp/services/*.sh Individual service startup scripts (emulator, metro, appium, app)
dev/mcp/lib/common.sh Shared utilities for process management and health checks
dev/mcp-stop.sh Cleanup script for all services
dev/mcp-start.sh Legacy startup script (delegates to orchestrator)
.mcp.json MCP server configuration for Claude Code
Makefile Added mcp-* targets for building and managing services
.gitignore Added .mcp/ and .beads/ exclusions

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@@ -0,0 +1,80 @@
// @ts-nocheck - WebDriverIO types are complex, runtime behavior is correct
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use "@ts-nocheck" because it alters compilation errors.

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,77 @@
// @ts-nocheck - MCP SDK type inference is complex
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use "@ts-nocheck" because it alters compilation errors.

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,71 @@
// @ts-nocheck - MCP SDK type inference is complex
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use "@ts-nocheck" because it alters compilation errors.

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,50 @@
// @ts-nocheck - MCP SDK type inference is complex
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use "@ts-nocheck" because it alters compilation errors.

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,39 @@
// @ts-nocheck - MCP SDK type inference is complex
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use "@ts-nocheck" because it alters compilation errors.

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,55 @@
// @ts-nocheck - MCP SDK type inference is complex
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use "@ts-nocheck" because it alters compilation errors.

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,53 @@
// @ts-nocheck - MCP SDK type inference is complex
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use "@ts-nocheck" because it alters compilation errors.

Copilot uses AI. Check for mistakes.

# Start Appium
cd "$PROJECT_DIR"
start_daemon "appium" "yarn appium --relaxed-security" || {
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Appium server is started with --relaxed-security and no explicit bind address, which typically exposes an unauthenticated Appium API with all security checks disabled on all network interfaces. An attacker on the same network could connect to port 4723 and invoke privileged Appium commands (e.g., filesystem and shell operations) against the emulator and potentially the host. Remove --relaxed-security for normal use, or at minimum bind Appium to 127.0.0.1 and tightly restrict insecure features to trusted, local-only workflows.

Copilot uses AI. Check for mistakes.
Makefile Outdated

# Start Appium server standalone
mcp-appium:
yarn appium --relaxed-security
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Makefile target starts Appium with --relaxed-security and no host restriction, which exposes an unauthenticated, security-relaxed Appium instance on port 4723 to the local network. A malicious user who can reach the developer machine could abuse this to drive the emulator and invoke powerful Appium commands, leading to data exfiltration or further compromise. Drop --relaxed-security here or ensure Appium is bound to 127.0.0.1 and that any insecure features are only enabled in tightly controlled local environments.

Copilot uses AI. Check for mistakes.
dev/mcp-start.sh Outdated

# 3. Appium
echo "Starting Appium..."
nohup yarn appium --relaxed-security > "$LOG_DIR/appium.log" 2>&1 &
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Starting Appium with --relaxed-security and no explicit --address means the server will typically listen on all interfaces with its security checks disabled. This allows anyone on the reachable network to hit port 4723 and use powerful Appium endpoints, potentially interacting with the emulator and accessing sensitive data without authentication. Remove --relaxed-security from this script or, if it is absolutely required, bind Appium to 127.0.0.1 and document that it must never be exposed beyond the local host.

Copilot uses AI. Check for mistakes.
Security:
- Bind Appium to 127.0.0.1 (localhost only)
- Update all scripts: services/appium.sh, mcp-start.sh, Makefile

TypeScript:
- client.ts: Remove @ts-nocheck, use proper WebDriverIO types
- tap.ts: Replace @ts-nocheck with targeted @ts-expect-error

Note: Other tool files still use @ts-nocheck due to MCP SDK's
complex recursive Zod type inference. Full migration requires
more investigation of SDK type exports.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@k9ert
Copy link
Contributor Author

k9ert commented Dec 17, 2025

The Typesystem fixes are absolut horrible for the agent. It's eating thousand of tokens and probably doesn't help much. Those are ulta complex types. Yes, it can be done but at which costs? And what are the beneefits?

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings December 17, 2025 16:45
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 37 out of 40 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1 to +14
// @ts-nocheck - MCP SDK type inference is complex
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import { AppiumClient } from "../appium/client.js";
import { buildSelector } from "../utils/selectors.js";

export function registerGetElementTool(server: McpServer, client: AppiumClient) {
server.tool(
"getElement",
"Get detailed info about one specific element by testID",
{
id: z.string().describe("Element testID"),
} as never,
async ({ id }: { id: string }) => {
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use "@ts-nocheck" because it alters compilation errors.

Suggested change
// @ts-nocheck - MCP SDK type inference is complex
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import { AppiumClient } from "../appium/client.js";
import { buildSelector } from "../utils/selectors.js";
export function registerGetElementTool(server: McpServer, client: AppiumClient) {
server.tool(
"getElement",
"Get detailed info about one specific element by testID",
{
id: z.string().describe("Element testID"),
} as never,
async ({ id }: { id: string }) => {
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import { AppiumClient } from "../appium/client.js";
import { buildSelector } from "../utils/selectors.js";
const getElementInputSchema = z.object({
id: z.string().describe("Element testID"),
});
type GetElementInput = z.infer<typeof getElementInputSchema>;
export function registerGetElementTool(server: McpServer, client: AppiumClient) {
server.tool(
"getElement",
"Get detailed info about one specific element by testID",
getElementInputSchema,
async ({ id }: GetElementInput) => {

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +15
// @ts-nocheck - MCP SDK type inference is complex
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import { AppiumClient } from "../appium/client.js";
import { parsePageSource, collectTestIds, type FilterType } from "../utils/xml-parser.js";

export function registerGetScreenTool(server: McpServer, client: AppiumClient) {
server.tool(
"getScreen",
"Get structured representation of all visible elements as JSON. Primary tool for understanding app state.",
{
maxDepth: z.number().optional().describe("Max nesting depth (default: 10)"),
filter: z.enum(["all", "interactive", "text"]).optional().describe("Filter: all, interactive, or text"),
} as never,
async ({ maxDepth = 10, filter = "all" }: { maxDepth?: number; filter?: string }) => {
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use "@ts-nocheck" because it alters compilation errors.

Suggested change
// @ts-nocheck - MCP SDK type inference is complex
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import { AppiumClient } from "../appium/client.js";
import { parsePageSource, collectTestIds, type FilterType } from "../utils/xml-parser.js";
export function registerGetScreenTool(server: McpServer, client: AppiumClient) {
server.tool(
"getScreen",
"Get structured representation of all visible elements as JSON. Primary tool for understanding app state.",
{
maxDepth: z.number().optional().describe("Max nesting depth (default: 10)"),
filter: z.enum(["all", "interactive", "text"]).optional().describe("Filter: all, interactive, or text"),
} as never,
async ({ maxDepth = 10, filter = "all" }: { maxDepth?: number; filter?: string }) => {
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import { AppiumClient } from "../appium/client.js";
import { parsePageSource, collectTestIds, type FilterType } from "../utils/xml-parser.js";
export function registerGetScreenTool(server: McpServer, client: AppiumClient) {
(server as any).tool(
"getScreen",
"Get structured representation of all visible elements as JSON. Primary tool for understanding app state.",
{
maxDepth: z.number().optional().describe("Max nesting depth (default: 10)"),
filter: z.enum(["all", "interactive", "text"]).optional().describe("Filter: all, interactive, or text"),
} as never,
async (args: any) => {
const { maxDepth = 10, filter = "all" } = args ?? {};

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,55 @@
// @ts-nocheck - MCP SDK type inference is complex
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use "@ts-nocheck" because it alters compilation errors.

Suggested change
// @ts-nocheck - MCP SDK type inference is complex
// MCP SDK type inference is complex

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,55 @@
// @ts-nocheck - MCP SDK type inference is complex
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use "@ts-nocheck" because it alters compilation errors.

Suggested change
// @ts-nocheck - MCP SDK type inference is complex
// MCP SDK type inference is complex

Copilot uses AI. Check for mistakes.
k9ert and others added 2 commits December 17, 2025 17:56
- Revert .gitattributes (remove beads merge driver)
- Remove dev/mcp/app-cli.sh (replaced by TypeScript CLI)
- Remove dev/mcp-start.sh (replaced by orchestrator.sh)
- Remove dev/start-all.sh (backwards compat wrapper)
- Move AGENT_GUIDE.md to dev/ for better visibility
- Update mcp-stop.sh comment

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Simple wrapper: ./dev/app tap "Login"
- Update AGENT_GUIDE.md with new CLI usage

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings December 17, 2025 17:13
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 34 out of 37 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1 to +7
// @ts-nocheck - MCP SDK type inference is complex
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import { AppiumClient } from "../appium/client.js";
import { parsePageSource, collectTestIds, type FilterType } from "../utils/xml-parser.js";

export function registerGetScreenTool(server: McpServer, client: AppiumClient) {
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use "@ts-nocheck" because it alters compilation errors.

Suggested change
// @ts-nocheck - MCP SDK type inference is complex
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import { AppiumClient } from "../appium/client.js";
import { parsePageSource, collectTestIds, type FilterType } from "../utils/xml-parser.js";
export function registerGetScreenTool(server: McpServer, client: AppiumClient) {
// Note: MCP SDK type inference is complex and may not align perfectly with our zod schemas.
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import { AppiumClient } from "../appium/client.js";
import { parsePageSource, collectTestIds, type FilterType } from "../utils/xml-parser.js";
export function registerGetScreenTool(server: McpServer, client: AppiumClient) {
// @ts-expect-error - MCP SDK tool typing is not fully compatible with this zod-based schema definition

Copilot uses AI. Check for mistakes.
k9ert and others added 6 commits December 22, 2025 12:26
- split cli.ts into basic, ux, helpers, config
- simplify ui command output (flat list, -j for JSON)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- ux login waits for user to solve captcha (2min timeout)
- polls for Geetest element, auto-continues when solved
- use waitForElement instead of sleep+verify for reliability
- comprehensive AGENT_GUIDE update with all CLI docs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- app launch/kill/restart/clear/info commands
- adb() now throws on failure, adbSafe() for graceful fallback
- update AGENT_GUIDE with new commands

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings December 22, 2025 20:57
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 42 out of 46 changed files in this pull request and generated 11 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@@ -0,0 +1,53 @@
// @ts-nocheck - MCP SDK type inference is complex
Copy link

Copilot AI Dec 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TypeScript strict mode is enabled but @ts-nocheck suppresses all type checking in this file. This defeats the purpose of TypeScript. Instead, fix the actual type issues or use targeted @ts-expect-error comments.

Copilot uses AI. Check for mistakes.
Comment on lines +40 to +41
# --relaxed-security: required for shell commands (hot reload) and app management
start_daemon "appium" "yarn appium --address 127.0.0.1 --relaxed-security" || {
Copy link

Copilot AI Dec 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Appium server is started with --relaxed-security flag which disables important security checks. This is documented as required for shell commands, but exposes the server to potential abuse. Consider documenting specific security implications and ensuring the server is bound to localhost only (which is done correctly via --address 127.0.0.1).

Copilot uses AI. Check for mistakes.
# 4. Blink app (install + launch)

set -euo pipefail
source "$(dirname "$0")/lib/common.sh"
Copy link

Copilot AI Dec 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The script sources common.sh using a relative path derived from the script's directory. If the script is invoked via symlink, this could potentially source the wrong file. Consider using realpath to resolve symlinks before sourcing.

Copilot uses AI. Check for mistakes.
echo "=== $name started at $(date) ===" >> "$log_file"

# Start with nohup, redirect output
nohup bash -c "$cmd" >> "$log_file" 2>&1 &
Copy link

Copilot AI Dec 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shell command is constructed by concatenating user input without proper escaping. Although cmd is currently hardcoded in calling contexts, this pattern is risky. Consider using array-based command execution or explicit quoting.

Copilot uses AI. Check for mistakes.
Comment on lines 154 to 176
export function parsePageSource(
xml: string,
options: { maxDepth?: number; filter?: FilterType } = {},
): ElementNode | null {
const { maxDepth = 10, filter = "all" } = options;

try {
const parsed = parser.parse(xml);

// Find root element (usually hierarchy or android.widget.FrameLayout)
const rootKey = Object.keys(parsed).find((k) => !k.startsWith("?"));
if (!rootKey) return null;

return convertNode(
parsed as Record<string, unknown>,
filter,
0,
maxDepth,
);
} catch (error) {
console.error("Failed to parse page source:", error);
return null;
}
Copy link

Copilot AI Dec 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The XML parser converts attribute names but doesn't validate or sanitize the input. If malicious XML is provided (e.g., from a compromised app or emulator), this could lead to unexpected behavior. Consider adding XML validation or size limits.

Copilot uses AI. Check for mistakes.
Comment on lines +41 to +56
const timeout = setTimeout(() => {
proc.kill();
resolve({
content: [
{
type: "text",
text: JSON.stringify({
success: false,
error: "Timeout after 5 minutes",
output: stdout.slice(-2000),
}, null, 2),
},
],
isError: true,
});
}, 300000);
Copy link

Copilot AI Dec 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 5-minute timeout is hardcoded. For slower systems or cold emulator boots, this may be insufficient. Consider making this configurable via environment variable or adding a warning in documentation about expected timing.

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,160 @@
import { execSync } from "child_process";
import { Command } from "commander";
import { adb, adbSafe, tapElement, typeText, getUiHierarchy, collectTestIds, collectUiInfo } from "./helpers.js";
Copy link

Copilot AI Dec 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'collectTestIds' is defined but never used.

Suggested change
import { adb, adbSafe, tapElement, typeText, getUiHierarchy, collectTestIds, collectUiInfo } from "./helpers.js";
import { adb, adbSafe, tapElement, typeText, getUiHierarchy, collectUiInfo } from "./helpers.js";

Copilot uses AI. Check for mistakes.
hasElement,
waitForElement,
waitForAny,
verifyScreen,
Copy link

Copilot AI Dec 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'verifyScreen' is defined but never used.

Suggested change
verifyScreen,

Copilot uses AI. Check for mistakes.
waitForElement,
waitForAny,
verifyScreen,
getElementText,
Copy link

Copilot AI Dec 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'getElementText' is defined but never used.

Suggested change
getElementText,

Copilot uses AI. Check for mistakes.
Comment on lines 2 to 18
import {
adb,
sleep,
goHome,
tapElement,
tapAndWait,
typeText,
clearInput,
hasElement,
waitForElement,
waitForAny,
verifyScreen,
getElementText,
getUiHierarchy,
collectTestIds,
collectUiInfo,
} from "./helpers.js";
Copy link

Copilot AI Dec 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused imports getElementText, verifyScreen.

Copilot uses AI. Check for mistakes.
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