-
Notifications
You must be signed in to change notification settings - Fork 384
feat: Add getCurrentActivity tool for unified app/activity detection #266
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
sh3lan93
wants to merge
8
commits into
mobile-next:main
Choose a base branch
from
sh3lan93:feature/introduce_get_current_activity_tool
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
8b81d78
feat: introduce getCurrentActivity method for Android and iOS
sh3lan93 fb67e06
refactor: improve getCurrentActivity robustness and unify iOS parsing
sh3lan93 70250d6
refactor: demote name fallback in WDA app ID parsing
sh3lan93 dd19d16
feat: implement session-based bundle ID fallback for iOS
sh3lan93 df12b14
refactor: add sessionId guard and document identifier resolution
sh3lan93 b687518
refactor: return discriminated union from getCurrentActivity
sh3lan93 646a3ac
refactor: update device guards to support multi-device testing
sh3lan93 8802ff3
test: use assert.strictEqual for activity ID comparison
sh3lan93 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| import assert from "node:assert"; | ||
|
|
||
| import { AndroidRobot, AndroidDeviceManager } from "../src/android"; | ||
| import { IosRobot, IosManager } from "../src/ios"; | ||
|
|
||
| const androidManager = new AndroidDeviceManager(); | ||
| const androidDevices = androidManager.getConnectedDevices(); | ||
| const hasAndroidDevice = androidDevices.length === 1; | ||
|
|
||
| const iosManager = new IosManager(); | ||
| const iosDevices = iosManager.listDevices(); | ||
| const hasIosDevice = iosDevices.length === 1; | ||
coderabbitai[bot] marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| describe("getCurrentActivity", () => { | ||
| describe("Android", () => { | ||
| const android = new AndroidRobot(androidDevices?.[0]?.deviceId || ""); | ||
|
|
||
| it("should return current activity as object with id field", async function() { | ||
| hasAndroidDevice || this.skip(); | ||
|
|
||
| // First, ensure we're on the home screen | ||
| await android.pressButton("HOME"); | ||
|
|
||
| // Get current activity | ||
| const activity = await android.getCurrentActivity(); | ||
|
|
||
| // Should return an object with id field | ||
| assert.ok(activity, "Activity should be defined"); | ||
| assert.ok("id" in activity, "Activity should have an id field"); | ||
| assert.ok(typeof activity.id === "string", "Activity id should be a string"); | ||
| assert.ok(activity.id.length > 0, "Activity id should not be empty"); | ||
| }); | ||
|
|
||
| it("should return correct package name after launching an app", async function() { | ||
| hasAndroidDevice || this.skip(); | ||
|
|
||
| const testAppPackage = "com.android.settings"; | ||
|
|
||
| // Launch the settings app | ||
| await android.launchApp(testAppPackage); | ||
|
|
||
| // Small delay to ensure app is focused | ||
| await new Promise(resolve => setTimeout(resolve, 500)); | ||
|
|
||
| const activity = await android.getCurrentActivity(); | ||
| assert.equal(activity.id, testAppPackage, `Expected ${testAppPackage} but got ${activity.id}`); | ||
coderabbitai[bot] marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| }); | ||
|
|
||
| it("should throw ActionableError if no activity in focus", async function() { | ||
| // This test is skipped as it's difficult to reliably create a state | ||
| // where no activity is in focus on a real device | ||
| this.skip(); | ||
| }); | ||
| }); | ||
|
|
||
| describe("iOS", () => { | ||
| const ios = new IosRobot(iosDevices?.[0]?.deviceId || ""); | ||
|
|
||
| it("should return current activity as object with id field", async function() { | ||
| hasIosDevice || this.skip(); | ||
|
|
||
| try { | ||
| const activity = await ios.getCurrentActivity(); | ||
|
|
||
| // Should return an object with id field | ||
| assert.ok(activity, "Activity should be defined"); | ||
| assert.ok("id" in activity, "Activity should have an id field"); | ||
| assert.ok(typeof activity.id === "string", "Activity id should be a string"); | ||
| assert.ok(activity.id.length > 0, "Activity id should not be empty"); | ||
| } catch (error: any) { | ||
| // Skip if tunnel is not running or other setup issues | ||
| if (error.message.includes("tunnel") || error.message.includes("WebDriver")) { | ||
| this.skip(); | ||
| } else { | ||
| throw error; | ||
| } | ||
| } | ||
| }); | ||
|
|
||
| it("should return bundle ID format", async function() { | ||
| hasIosDevice || this.skip(); | ||
|
|
||
| try { | ||
| const activity = await ios.getCurrentActivity(); | ||
|
|
||
| // Bundle IDs typically contain dots (e.g., com.apple.mobilesafari) | ||
| // or are single words like "Health", "Maps", etc. | ||
| assert.ok(activity.id.length > 0, "Bundle ID should not be empty"); | ||
|
|
||
| // Try to launch an app and verify we get its bundle ID | ||
| // Using com.apple.mobilesafari as it's typically available | ||
| await ios.launchApp("com.apple.mobilesafari"); | ||
|
|
||
| const newActivity = await ios.getCurrentActivity(); | ||
| assert.ok(newActivity.id.length > 0, "New activity id should not be empty"); | ||
| } catch (error: any) { | ||
| // Skip if tunnel is not running or other setup issues | ||
| if (error.message.includes("tunnel") || error.message.includes("WebDriver")) { | ||
| this.skip(); | ||
| } else { | ||
| throw error; | ||
| } | ||
| } | ||
| }); | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| }); | ||
| }); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.