Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 21 additions & 109 deletions .github/instructions/appium-control.instructions.md
Copy link
Member

Choose a reason for hiding this comment

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

@copilot

Should this file still have instructions about build and run for ios apps?

It seems like most of this file can go away yea?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're correct - removed 106 lines of redundant build/deploy instructions (commit 53fc42c).

The file now focuses on its core purpose: teaching how to write Appium C# scripts for manual debugging. Removed:

  • Manual iOS/Android build/deploy commands (now handled by BuildAndRunSandbox.ps1)
  • Manual Appium startup/cleanup instructions (script handles this)
  • Redundant UDID extraction patterns (script handles this)

Kept:

  • Appium scripting template and syntax guidance
  • Platform differences (iOS vs Android element locators)
  • Common Appium operations examples
  • Troubleshooting section

The file is now 365 lines (was 471), with all build/deploy workflows delegated to the script.

Original file line number Diff line number Diff line change
Expand Up @@ -31,101 +31,30 @@ This repository uses **.NET 10's built-in scripting features** with the `#:packa

## Quick Start with Sandbox App

The fastest way to experiment with Appium is using the Sandbox app (`src/Controls/samples/Controls.Sample.Sandbox`):
**Use BuildAndRunSandbox.ps1 Script**

1. **Modify `MainPage.xaml`** to add controls with `AutomationId` attributes
The script handles all building, deployment, Appium management, and log capture:

2. **Build and deploy**:
```powershell
# 1. Copy Appium template
cp .github/scripts/templates/RunWithAppiumTest.template.cs SandboxAppium/RunWithAppiumTest.cs

**iOS:**
```bash
# Build
dotnet build src/Controls/samples/Controls.Sample.Sandbox/Maui.Controls.Sample.Sandbox.csproj -f net10.0-ios
# 2. Edit the template for your test scenario

# Get device UDID
UDID=$(xcrun simctl list devices available --json | jq -r '.devices | to_entries | map(select(.key | startswith("com.apple.CoreSimulator.SimRuntime.iOS"))) | map({key: .key, version: (.key | sub("com.apple.CoreSimulator.SimRuntime.iOS-"; "") | split("-") | map(tonumber)), devices: .value}) | sort_by(.version) | reverse | map(select(.devices | any(.name == "iPhone Xs"))) | first | .devices[] | select(.name == "iPhone Xs") | .udid')

# Verify UDID was found
if [ -z "$UDID" ]; then
echo "❌ ERROR: No iPhone Xs simulator found"
exit 1
fi
echo "Using iPhone Xs with UDID: $UDID"

# Boot and install
xcrun simctl boot $UDID 2>/dev/null || true
xcrun simctl install $UDID artifacts/bin/Maui.Controls.Sample.Sandbox/Debug/net10.0-ios/iossimulator-arm64/Maui.Controls.Sample.Sandbox.app

# Set environment variable
export DEVICE_UDID=$UDID
```

**Android:**
```bash
# Get device UDID
UDID=$(adb devices | grep -v "List" | grep "device" | awk '{print $1}' | head -1)

# Verify UDID was found
if [ -z "$UDID" ]; then
echo "❌ ERROR: No Android device/emulator found"
exit 1
fi
echo "Using Android device: $UDID"

# Set environment variable
export DEVICE_UDID=$UDID

# Build and deploy (this handles install + launch)
dotnet build src/Controls/samples/Controls.Sample.Sandbox/Maui.Controls.Sample.Sandbox.csproj -f net10.0-android -t:Run

# Verify app is running
sleep 3
if adb -s $UDID shell pidof com.microsoft.maui.sandbox > /dev/null; then
echo "✅ App is running"
else
echo "❌ App failed to start"
exit 1
fi
```

3. **Start Appium and run your control script**:
```bash
# Start Appium in background
appium --log-level error &

# Wait for Appium to be ready
sleep 3

# Or verify it's ready (optional):
# curl http://localhost:4723/status

# Run your script (from SandboxAppium/ directory)
cd SandboxAppium

# Run with .NET 10's native scripting (NOT dotnet-script)
dotnet run yourscript.cs
```

**Note**: The Sandbox app and SandboxAppium folder are set up for iterative development. You can modify your script and re-run it multiple times without cleaning up. Only clean up when you're completely done with your debugging session.

## Cleanup (Optional)

When you're finished with your debugging session and ready to clean up:

```bash
# Revert Sandbox changes
git checkout -- src/Controls/samples/Controls.Sample.Sandbox/
# 3. Run everything with one command
pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform [android|ios]
```

# Remove SandboxAppium folder (it's gitignored)
rm -rf SandboxAppium
The script automatically:
- Detects and boots devices
- Builds and deploys the Sandbox app
- Starts/stops Appium server
- Runs your Appium test script
- Captures all logs to `SandboxAppium/` directory

# Kill Appium server
lsof -i :4723 | grep LISTEN | awk '{print $2}' | xargs kill -9
```
See [Common Testing Patterns](common-testing-patterns.md) for details.

## Prerequisites

Ensure Appium server is running on `http://localhost:4723` before running your script.

## Basic Template

Expand Down Expand Up @@ -248,6 +177,10 @@ catch (Exception ex)

## Running the Script

**The BuildAndRunSandbox.ps1 script handles all setup and execution.** See [Quick Start with Sandbox App](#quick-start-with-sandbox-app) for the complete workflow.

**For manual/standalone script execution** (advanced scenarios):

**🚨 CRITICAL: .NET 10 Native Scripting (NOT dotnet-script)**

- ✅ **DO**: Use `dotnet run yourscript.cs` (.NET 10 native scripting)
Expand All @@ -258,28 +191,7 @@ catch (Exception ex)

**⚠️ Important: Create scripts inside project directory (e.g., `SandboxAppium/`), not in `/tmp` or repository root.**

```bash
# 1. Create script folder
mkdir -p SandboxAppium && cd SandboxAppium

# 2. Copy the Basic Template above into a .cs file (or use the Quick Start example)

# 3. Set DEVICE_UDID environment variable
export DEVICE_UDID=$(xcrun simctl list devices available --json | jq -r '.devices | to_entries | map(select(.key | startswith("com.apple.CoreSimulator.SimRuntime.iOS"))) | map({key: .key, version: (.key | sub("com.apple.CoreSimulator.SimRuntime.iOS-"; "") | split("-") | map(tonumber)), devices: .value}) | sort_by(.version) | reverse | map(select(.devices | any(.name == "iPhone Xs"))) | first | .devices[] | select(.name == "iPhone Xs") | .udid')

# 4. Start Appium (separate terminal or background)
appium --log-level error &

# Wait for Appium to be ready
sleep 3

# 5. Run your script
dotnet run yourscript.cs
```

**For Android:** Replace iOS UDID command with: `adb devices | grep -v "List" | grep "device" | awk '{print $1}' | head -1`

**Complete workflow:** See [Quick Start with Sandbox App](#quick-start-with-sandbox-app) above for full end-to-end example.
For manual execution details, see [Common Testing Patterns](common-testing-patterns.md).

## ❌ Wrong vs ✅ Right Approach

Expand Down
24 changes: 19 additions & 5 deletions .github/instructions/instrumentation.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,26 @@ namespace Maui.Controls.Sample

### Step 3: Build, Deploy, and Capture

See [Common Testing Patterns](common-testing-patterns.md) for detailed build and deploy commands:
**⚡ Option A: Use BuildAndRunSandbox.ps1 Script (Recommended)**

**iOS**: [Sandbox App Build (iOS)](common-testing-patterns.md#sandbox-app-build-ios)
**Android**: [Sandbox App Build (Android)](common-testing-patterns.md#sandbox-app-build-android)
When using with Appium for UI interaction:

**Quick iOS workflow:**
```powershell
# 1. Create Appium test script with your instrumentation logic
cp .github/scripts/templates/RunWithAppiumTest.template.cs SandboxAppium/RunWithAppiumTest.cs
# Edit RunWithAppiumTest.cs to add your test logic

# 2. Run everything with one command
pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform [android|ios]
```

The script handles device detection, building, deployment, Appium management, and log capture. See [Common Testing Patterns](common-testing-patterns.md) for details.

---

**Option B: Manual Build and Capture** (for console-only instrumentation without Appium):

**iOS**:
```bash
# Get UDID, boot, build, install, launch
UDID=$(xcrun simctl list devices available --json | jq -r '.devices | to_entries | map(select(.key | startswith("com.apple.CoreSimulator.SimRuntime.iOS"))) | map({key: .key, version: (.key | sub("com.apple.CoreSimulator.SimRuntime.iOS-"; "") | split("-") | map(tonumber)), devices: .value}) | sort_by(.version) | reverse | map(select(.devices | any(.name == "iPhone Xs"))) | first | .devices[] | select(.name == "iPhone Xs") | .udid')
Expand All @@ -153,7 +167,7 @@ xcrun simctl launch --console-pty $UDID com.microsoft.maui.sandbox > /tmp/output
sleep 8 && cat /tmp/output.log
```

**Quick Android workflow:**
**Android**:
```bash
export DEVICE_UDID=$(adb devices | grep -v "List" | grep "device" | awk '{print $1}' | head -1)
dotnet build src/Controls/samples/Controls.Sample.Sandbox/Maui.Controls.Sample.Sandbox.csproj -f net10.0-android -t:Run
Expand Down
71 changes: 26 additions & 45 deletions .github/instructions/pr-reviewer-agent/error-handling.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,36 +150,23 @@ fi

**Step 1: ATTEMPT available solutions first**

For Android:
```bash
# 1. Check for device
export DEVICE_UDID=$(adb devices | grep -v "List" | grep "device" | awk '{print $1}' | head -1)

# 2. If no device, START EMULATOR (don't give up!)
if [ -z "$DEVICE_UDID" ]; then
echo "No device found. Starting emulator..."
cd $ANDROID_HOME/emulator && (./emulator -avd Pixel_9 -no-snapshot-load -no-audio -no-boot-anim > /tmp/emulator.log 2>&1 &)
adb wait-for-device
until [ "$(adb shell getprop sys.boot_completed 2>/dev/null)" = "1" ]; do
sleep 2
done
export DEVICE_UDID=$(adb devices | grep -v "List" | grep "device" | awk '{print $1}' | head -1)
fi

# 3. If emulator failed, check logs
if [ -z "$DEVICE_UDID" ]; then
echo "Emulator failed to start. Checking logs..."
cat /tmp/emulator.log
# Now proceed to Step 2 (checkpoint)
fi
**For both Android and iOS**: Use the BuildAndRunSandbox.ps1 script, which handles device detection and emulator startup automatically:

```powershell
# The script will:
# 1. Auto-detect devices
# 2. Start emulator/simulator if no device found (Android only - prompts for confirmation)
# 3. Build and deploy Sandbox app
# 4. Run your Appium test

pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform android
# OR
pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform ios
```

For iOS:
```bash
# Check for available simulators
xcrun simctl list devices | grep iPhone
# Attempt to boot simulator (see quick-ref.md)
```
**If the script fails**, check the log files in `SandboxAppium/`:
- `appium.log` - Appium server issues
- `android-device.log` or `ios-device.log` - Device/app issues

**Step 2: If solutions fail, CREATE CHECKPOINT (don't skip testing!)**

Expand Down Expand Up @@ -226,28 +213,22 @@ After attempting solutions and hitting genuine blocker:
**How to avoid**:
1. **Read appium-control.instructions.md FIRST** before attempting UI interaction
2. Remember: Appium is REQUIRED for reliability (element-based vs coordinate-based)
3. **Use .cs files with `dotnet run`** (NOT .csx files with dotnet-script)
3. **Use the Appium template** from `.github/scripts/templates/RunWithAppiumTest.template.cs`
4. When Appium fails, debug the Appium approach (don't fall back to adb)
5. **Internalize instructions, don't just skim them**

**Complete sequence**:
```bash
# 1. Create Appium script (.cs file, NOT .csx)
cat > test_pr_XXXXX.cs << 'EOF'
#r "nuget: Appium.WebDriver, 8.0.1"
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.Android;

var options = new AppiumOptions();
options.AddAdditionalAppiumOption("platformName", "Android");
options.AddAdditionalAppiumOption("automationName", "UIAutomator2");
options.AddAdditionalAppiumOption("appPackage", "com.microsoft.maui.sandbox");
options.AddAdditionalAppiumOption("appActivity", "crc64..MainActivity");
options.AddAdditionalAppiumOption("noReset", true);

var driver = new AndroidDriver(new Uri("http://127.0.0.1:4723"), options);

// Find and tap button by AutomationId
# 1. Copy Appium template to SandboxAppium directory
cp .github/scripts/templates/RunWithAppiumTest.template.cs SandboxAppium/RunWithAppiumTest.cs

# 2. Edit the file to customize:
# - Set ISSUE_NUMBER constant
# - Set PLATFORM constant ("android" or "ios")
# - Implement test logic in the "Test Logic" section

# 3. Run with BuildAndRunSandbox.ps1 script
pwsh .github/scripts/BuildAndRunSandbox.ps1 -Platform android
var button = driver.FindElement(MobileBy.AccessibilityId("TestButton"));
button.Click();

Expand Down
Loading