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
3 changes: 1 addition & 2 deletions .github/actions/setup-xcode/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ runs:
- name: Setup Xcode version
shell: bash
run: |
sudo xcode-select -s /Applications/Xcode_16.2.app/Contents/Developer
xcodebuild -downloadPlatform iOS -buildVersion 18.2
sudo xcode-select -s /Applications/Xcode_16.4.app
/usr/bin/xcodebuild -version

- name: Cache Xcode DerivedData
Expand Down
82 changes: 82 additions & 0 deletions .github/workflows/compose-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ jobs:
compose-ios-tests:
runs-on: macos-15-xlarge
name: Compose iOS Tests
env:
GRADLE_OPTS: -Xmx12g -Dorg.gradle.daemon=false
steps:
- name: Checkout Repository
uses: actions/checkout@v5
Expand All @@ -67,6 +69,86 @@ jobs:
paths: "out/**/build/test-results/**/TEST-*.xml"
if: always()

compose-ios-utils-tests:
runs-on: macos-15-xlarge
name: Compose iOS Utils Tests
env:
GRADLE_OPTS: -Xmx12g -Dorg.gradle.daemon=false
steps:
- name: Checkout Repository
uses: actions/checkout@v5

- name: Setup Prerequisites
uses: ./.github/actions/setup-prerequisites

- name: Setup Xcode
uses: ./.github/actions/setup-xcode

- name: Run iOS Utils Tests
timeout-minutes: 15
shell: bash
working-directory: compose/ui/ui-uikit/src/uikitMain/objc/CMPUIKitUtils
run: |
xcodebuild test \
-resultBundlePath TestResults.xcresult \
-scheme CMPUIKitUtilsTests \
-project CMPUIKitUtils.xcodeproj \
-destination 'platform=iOS Simulator,name=iPhone 16'

- name: Upload Test Results
uses: actions/upload-artifact@v4
if: failure()
with:
name: TestResults-${{ github.run_number }}.xcresult
path: compose/ui/ui-uikit/src/uikitMain/objc/CMPUIKitUtils/TestResults.xcresult

compose-ios-instrumented-tests:
runs-on: macos-15-xlarge
name: Compose iOS Instrumented Tests
env:
GRADLE_OPTS: -Xmx12g -Dorg.gradle.daemon=false
steps:
- name: Checkout Repository
uses: actions/checkout@v5

- name: Setup Prerequisites
uses: ./.github/actions/setup-prerequisites

- name: Setup Xcode
uses: ./.github/actions/setup-xcode

- name: Configure Simulator
run: |
xcrun simctl list devices

# Boot a test simulator
xcrun simctl boot "iPhone 16"

# Write the accessibility flags inside the Simulator:
xcrun simctl spawn booted defaults write com.apple.Accessibility AccessibilityEnabled -bool true
xcrun simctl spawn booted defaults write com.apple.Accessibility ApplicationAccessibilityEnabled -bool true
xcrun simctl spawn booted defaults write com.apple.Accessibility AutomationEnabled -bool true

# Restart SpringBoard (so system services pick up the change)
xcrun simctl spawn booted launchctl stop com.apple.SpringBoard
xcrun simctl shutdown all

- name: Run iOS Instrumented Tests
timeout-minutes: 30
shell: bash
working-directory: compose/ui/ui/src/uikitInstrumentedTest/launcher
run: |
xcodebuild test \
-scheme Launcher \
-project Launcher.xcodeproj \
-destination 'platform=iOS Simulator,name=iPhone 16'

- name: Test Summary
uses: test-summary/action@v2
with:
paths: "**/reports/junit.xml"
if: always()

compose-web-chrome-tests:
runs-on: ubuntu-24.04
name: Compose Web Chrome Tests
Expand Down
51 changes: 0 additions & 51 deletions .jb-ciscripts/PullRequests/UIKitInstrumentedTests.sh

This file was deleted.

3 changes: 0 additions & 3 deletions .jb-ciscripts/README.md

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.material.TextField
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
Expand Down Expand Up @@ -131,7 +134,7 @@ class BasicInteractionTest {
}
}

findNodeWithTag("TextField").doubleTap()
openToolbar(textFieldTag = "TextField")

verifyFullToolbarPresent()
}
Expand All @@ -146,7 +149,7 @@ class BasicInteractionTest {
}
}

findNodeWithTag("TextField").doubleTap()
openToolbar(textFieldTag = "TextField")

verifyFullToolbarPresent()
}
Expand All @@ -160,7 +163,7 @@ class BasicInteractionTest {
}
}

findNodeWithTag("TextField").doubleTap()
openToolbar(textFieldTag = "TextField")

verifyFullToolbarPresent()
}
Expand All @@ -175,7 +178,7 @@ class BasicInteractionTest {
}
}

findNodeWithTag("TextField").doubleTap()
openToolbar(textFieldTag = "TextField")

verifyFullToolbarPresent()
}
Expand All @@ -196,7 +199,7 @@ class BasicInteractionTest {
fun MutableState<TextFieldValue>.isFullySelected(): Boolean =
value.selection.start == 0 && value.selection.end == value.text.length

findNodeWithTag("TextField").doubleTap()
openToolbar(textFieldTag = "TextField")

waitForContextMenu()
assertFalse(textFieldValue.isFullySelected())
Expand All @@ -219,7 +222,7 @@ class BasicInteractionTest {
fun TextFieldState.isFullySelected(): Boolean =
selection.start == 0 && selection.end == text.length

findNodeWithTag("TextField").doubleTap()
openToolbar(textFieldTag = "TextField")

waitForContextMenu()
assertFalse(textFieldState.isFullySelected())
Expand All @@ -230,6 +233,13 @@ class BasicInteractionTest {
assertTrue(textFieldState.isFullySelected())
}

private fun UIKitInstrumentedTest.openToolbar(textFieldTag: String) {
findNodeWithTag("TextField").tap()
delay(500)
findNodeWithTag("TextField").doubleTap()
waitForContextMenu()
}

@OptIn(ExperimentalFoundationApi::class)
private fun runContextMenuTest(
newContextMenuEnabled: Boolean,
Expand All @@ -246,9 +256,6 @@ class BasicInteractionTest {

@OptIn(ExperimentalForeignApi::class)
private fun UIKitInstrumentedTest.verifyFullToolbarPresent() {
// Verify elements from context menu present
waitForContextMenu()

findNodeWithLabel("Cut").let {
it.assertVisibleInContainer()
assertTrue(it.isAccessibilityElement ?: false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,14 +331,22 @@ internal fun UIKitInstrumentedTest.assertAccessibilityTree(
}

internal fun UIKitInstrumentedTest.findNodeWithTag(tag: String) = findNodeWithTagOrNull(tag)
?: fail("Unable to find node with identifier: $tag")
?: run {
println("Actual accessibility tree:")
println(getAccessibilityTree().printTree())
fail("Unable to find node with identifier: $tag")
}

internal fun UIKitInstrumentedTest.findNodeWithTagOrNull(tag: String) = firstNodeOrNull {
it.identifier == tag
}

internal fun UIKitInstrumentedTest.findNodeWithLabel(label: String) = findNodeWithLabelOrNull(label)
?: fail("Unable to find node with label: $label")
?: run {
println("Actual accessibility tree:")
println(getAccessibilityTree().printTree())
fail("Unable to find node with label: $label")
}

internal fun UIKitInstrumentedTest.findNodeWithLabelOrNull(label: String) = firstNodeOrNull {
it.label == label
Expand Down
Loading