diff --git a/eng/helix_xharness.proj b/eng/helix_xharness.proj
index 8778486c692d..1f92825306e9 100644
--- a/eng/helix_xharness.proj
+++ b/eng/helix_xharness.proj
@@ -3,9 +3,14 @@
test/devices/
$(BUILD_BUILDNUMBER)
default
- osx.15.arm64.maui.open
- osx.15.arm64.maui.open
- ubuntu.2204.amd64.android.33.open
+
+ osx.15.arm64.maui.open
+ osx.15.arm64.maui.open
+ ubuntu.2204.amd64.android.33.open
+
+ osx.15.arm64.iphone.maui
+ osx.15.arm64.iphone.maui
+ ubuntu.2204.amd64.android.33
true
maui
true
@@ -110,7 +115,7 @@
02:00:00
01:15:00
00:10:00
- $([System.IO.Directory]::GetDirectories('$(ScenariosDir)Controls.DeviceTests/Release/$(TargetFrameworkToTest)-ios/', '*.app', System.IO.SearchOption.AllDirectories))
+ $([System.IO.Directory]::GetDirectories('$(ScenariosDir)Controls.DeviceTests/Release/net11.0-ios/', '*.app', System.IO.SearchOption.AllDirectories))
xharness apple test --target "$target" --app "$app" --output-directory "$output_directory" --timeout "$timeout" --launch-timeout "$launch_timeout" --set-env="TestFilter=Category=%(Identity)"
@@ -119,27 +124,27 @@
02:00:00
01:15:00
00:10:00
- $([System.IO.Directory]::GetDirectories('$(ScenariosDir)Controls.DeviceTests/Release/$(TargetFrameworkToTest)-ios/', '*.app', System.IO.SearchOption.AllDirectories))
+ $([System.IO.Directory]::GetDirectories('$(ScenariosDir)Controls.DeviceTests/Release/net11.0-ios/', '*.app', System.IO.SearchOption.AllDirectories))
xharness apple test --target "$target" --app "$app" --output-directory "$output_directory" --timeout "$timeout" --launch-timeout "$launch_timeout" --set-env="TestFilter=SkipCategories=$(ControlsTestCategoriesToSkipForRestOfTests)"
-
+
ios-simulator-64
02:00:00
01:00:00
-
+
ios-simulator-64
02:00:00
01:00:00
-
+
ios-simulator-64
02:00:00
01:00:00
-
+
ios-simulator-64
02:00:00
01:00:00
@@ -148,7 +153,7 @@
-
+
maccatalyst
02:00:00
01:00:00
@@ -158,7 +163,7 @@
- <_apks Include="%(_MAUIScenarioSearch.PayloadDirectory)/Release/$(TargetFrameworkToTest)-android/**/*Signed.apk" />
+ <_apks Include="%(_MAUIScenarioSearch.PayloadDirectory)/Release/net10.0-android/**/*Signed.apk" />
02:00:00
01:00:00
diff --git a/eng/pipelines/arcade/stage-device-tests.yml b/eng/pipelines/arcade/stage-device-tests.yml
index 5084754e7e5e..f0b4a1d95b6d 100644
--- a/eng/pipelines/arcade/stage-device-tests.yml
+++ b/eng/pipelines/arcade/stage-device-tests.yml
@@ -46,6 +46,9 @@ parameters:
- name: checkoutDirectory
type: string
default: $(System.DefaultWorkingDirectory)
+- name: HelixAccessToken
+ type: string
+ default: ''
stages:
- stage: devicetests_build
@@ -71,7 +74,7 @@ stages:
jobs:
- job: builddevice_tests
displayName: Build Device Tests (Mono)
- timeoutInMinutes: 60
+ timeoutInMinutes: 120
variables:
- name: _BuildConfig
value: ${{ parameters.BuildConfiguration }}
@@ -145,7 +148,11 @@ stages:
- template: /eng/common/templates-official/steps/send-to-helix.yml
parameters:
HelixProjectPath: ${{ parameters.helixProject }}
- HelixProjectArguments: /p:TargetOS=ios /p:TestRunNameSuffix=_$(_BuildConfig) /p:TestRunNamePrefix=DeviceTestsIOS_
+ ${{ if eq(parameters.runAsPublic, true) }}:
+ HelixProjectArguments: /p:TargetOS=ios /p:TestRunNameSuffix=_$(_BuildConfig) /p:TestRunNamePrefix=DeviceTestsIOS_ /p:HelixInternal=False
+ ${{ else }}:
+ HelixProjectArguments: /p:TargetOS=ios /p:TestRunNameSuffix=_$(_BuildConfig) /p:TestRunNamePrefix=DeviceTestsIOS_ /p:HelixInternal=True
+ HelixAccessToken: ${{ parameters.HelixAccessToken }}
HelixConfiguration: $(_BuildConfig)
IncludeDotNetCli: true
DisplayNamePrefix: DeviceTestsIOS
@@ -176,7 +183,7 @@ stages:
jobs:
- job: device_tests_maccatalyst
displayName: Run DeviceTests MacCatalyst (Mono)
- timeoutInMinutes: 60
+ timeoutInMinutes: 240
variables:
- name: _BuildConfig
value: ${{ parameters.BuildConfiguration }}
@@ -195,7 +202,11 @@ stages:
- template: /eng/common/templates-official/steps/send-to-helix.yml
parameters:
HelixProjectPath: ${{ parameters.helixProject }}
- HelixProjectArguments: /p:TargetOS=maccatalyst /p:TestRunNameSuffix=_$(_BuildConfig) /p:TestRunNamePrefix=DeviceTestsMacCatalyst_
+ ${{ if eq(parameters.runAsPublic, true) }}:
+ HelixProjectArguments: /p:TargetOS=maccatalyst /p:TestRunNameSuffix=_$(_BuildConfig) /p:TestRunNamePrefix=DeviceTestsMacCatalyst_ /p:HelixInternal=False
+ ${{ else }}:
+ HelixProjectArguments: /p:TargetOS=maccatalyst /p:TestRunNameSuffix=_$(_BuildConfig) /p:TestRunNamePrefix=DeviceTestsMacCatalyst_ /p:HelixInternal=True
+ HelixAccessToken: ${{ parameters.HelixAccessToken }}
HelixConfiguration: $(_BuildConfig)
IncludeDotNetCli: true
DisplayNamePrefix: DeviceTestsMacCatalyst
@@ -243,7 +254,11 @@ stages:
- template: /eng/common/templates-official/steps/send-to-helix.yml
parameters:
HelixProjectPath: ${{ parameters.helixProject }}
- HelixProjectArguments: /p:TargetOS=android /p:TestRunNameSuffix=_$(_BuildConfig) /p:TestRunNamePrefix=DeviceTestsAndroid_
+ ${{ if eq(parameters.runAsPublic, true) }}:
+ HelixProjectArguments: /p:TargetOS=android /p:TestRunNameSuffix=_$(_BuildConfig) /p:TestRunNamePrefix=DeviceTestsAndroid_ /p:HelixInternal=False
+ ${{ else }}:
+ HelixProjectArguments: /p:TargetOS=android /p:TestRunNameSuffix=_$(_BuildConfig) /p:TestRunNamePrefix=DeviceTestsAndroid_ /p:HelixInternal=True
+ HelixAccessToken: ${{ parameters.HelixAccessToken }}
HelixConfiguration: $(_BuildConfig)
IncludeDotNetCli: true
DisplayNamePrefix: DeviceTestsAndroid
@@ -272,7 +287,7 @@ stages:
jobs:
- job: builddevice_tests_coreclr
displayName: Build Device Tests (CoreCLR)
- timeoutInMinutes: 60
+ timeoutInMinutes: 120
variables:
- name: _BuildConfig
value: ${{ parameters.BuildConfiguration }}
@@ -346,7 +361,11 @@ stages:
- template: ${{ iif(eq(parameters.runAsPublic, 'true'), '/eng/common/templates/steps/send-to-helix.yml', '/eng/common/templates-official/steps/send-to-helix.yml@self') }}
parameters:
HelixProjectPath: ${{ parameters.helixProject }}
- HelixProjectArguments: /p:TargetOS=android /p:TestRunNameSuffix=_$(_BuildConfig)_CoreCLR /p:TestRunNamePrefix=DeviceTestsAndroid_CoreCLR_
+ ${{ if eq(parameters.runAsPublic, true) }}:
+ HelixProjectArguments: /p:TargetOS=android /p:TestRunNameSuffix=_$(_BuildConfig)_CoreCLR /p:TestRunNamePrefix=DeviceTestsAndroid_CoreCLR_ /p:HelixInternal=False
+ ${{ else }}:
+ HelixProjectArguments: /p:TargetOS=android /p:TestRunNameSuffix=_$(_BuildConfig)_CoreCLR /p:TestRunNamePrefix=DeviceTestsAndroid_CoreCLR_ /p:HelixInternal=True
+ HelixAccessToken: ${{ parameters.HelixAccessToken }}
HelixConfiguration: $(_BuildConfig)
IncludeDotNetCli: true
DisplayNamePrefix: DeviceTestsAndroid_CoreCLR
@@ -394,7 +413,7 @@ stages:
- template: ${{ iif(eq(parameters.runAsPublic, 'true'), '/eng/common/templates/steps/send-to-helix.yml', '/eng/common/templates-official/steps/send-to-helix.yml@self') }}
parameters:
HelixProjectPath: ${{ parameters.helixProject }}
- HelixProjectArguments: /p:TargetOS=ios /p:TestRunNameSuffix="_$(_BuildConfig)_CoreCLR" /p:TestRunNamePrefix="DeviceTestsIOS_CoreCLR_"
+ HelixProjectArguments: /p:TargetOS=ios /p:TestRunNameSuffix=_$(_BuildConfig)_CoreCLR /p:TestRunNamePrefix=DeviceTestsIOS_CoreCLR_
HelixConfiguration: $(_BuildConfig)
IncludeDotNetCli: true
DisplayNamePrefix: DeviceTestsIOS_CoreCLR
@@ -444,7 +463,7 @@ stages:
- template: ${{ iif(eq(parameters.runAsPublic, 'true'), '/eng/common/templates/steps/send-to-helix.yml', '/eng/common/templates-official/steps/send-to-helix.yml@self') }}
parameters:
HelixProjectPath: ${{ parameters.helixProject }}
- HelixProjectArguments: /p:TargetOS=maccatalyst /p:TestRunNameSuffix="_$(_BuildConfig)_CoreCLR" /p:TestRunNamePrefix="DeviceTestsMacCatalyst_CoreCLR_"
+ HelixProjectArguments: /p:TargetOS=maccatalyst /p:TestRunNameSuffix=_$(_BuildConfig)_CoreCLR /p:TestRunNamePrefix=DeviceTestsMacCatalyst_CoreCLR_
HelixConfiguration: $(_BuildConfig)
IncludeDotNetCli: true
DisplayNamePrefix: DeviceTestsMacCatalyst_CoreCLR
diff --git a/eng/pipelines/ci-device-tests.yml b/eng/pipelines/ci-device-tests.yml
index 2d97beb06379..617e1987fcad 100644
--- a/eng/pipelines/ci-device-tests.yml
+++ b/eng/pipelines/ci-device-tests.yml
@@ -47,10 +47,36 @@ variables:
- template: /eng/common/templates/variables/pool-providers.yml@self
- template: /eng/pipelines/common/variables.yml@self
- template: /eng/pipelines/arcade/variables.yml@self
+# Include Helix access token for internal builds
+- ${{ if eq(variables['System.TeamProject'], 'internal') }}:
+ - group: DotNet-HelixApi-Access
parameters:
-- name: windowsPool
+# Internal pools (dnceng)
+- name: windowsPoolInternal
+ type: object
+ default:
+ name: NetCore1ESPool-Internal
+ demands:
+ - ImageOverride -equals 1es-windows-2022
+ image: 1es-windows-2022
+ os: Windows
+
+- name: macOSTestPoolInternal
+ type: object
+ default:
+ name: Azure Pipelines
+ vmImage: macOS-15
+
+- name: macOSPoolInternal
+ type: object
+ default:
+ name: Azure Pipelines
+ vmImage: macOS-15
+
+# Public pools (dnceng-public)
+- name: windowsPoolPublic
type: object
default:
name: NetCore-Public
@@ -59,13 +85,13 @@ parameters:
image: 1es-windows-2022-open
os: Windows
-- name: macOSTestPool
+- name: macOSTestPoolPublic
type: object
default:
name: MAUI
vmImage: MAUI
-- name: macOSPool
+- name: macOSPoolPublic
type: object
default:
name: MAUI
@@ -84,10 +110,17 @@ stages:
# Use Helix for iOS / Android and MacCatalyst Device Tests
- template: /eng/pipelines/arcade/stage-device-tests.yml@self
parameters:
- buildPool: ${{ parameters.macOSPool }}
- testPool: ${{ parameters.windowsPool }}
- runAsPublic: true
- TargetFrameworkVersion: net11.0
+ # Select pools based on pipeline - internal vs public
+ ${{ if eq(variables['System.TeamProject'], 'internal') }}:
+ buildPool: ${{ parameters.macOSPoolInternal }}
+ testPool: ${{ parameters.windowsPoolInternal }}
+ runAsPublic: false
+ HelixAccessToken: $(HelixApiAccessToken)
+ ${{ else }}:
+ buildPool: ${{ parameters.macOSPoolPublic }}
+ testPool: ${{ parameters.windowsPoolPublic }}
+ runAsPublic: true
+ TargetFrameworkVersion: ${{ targetFrameworkVersion.tfm }}
prepareSteps:
- template: /eng/pipelines/common/provision.yml@self
parameters:
@@ -104,7 +137,10 @@ stages:
# Just use the old way for Windows Device Tests
- template: common/device-tests.yml
parameters:
- windowsPool: ${{ parameters.windowsPool }}
+ ${{ if eq(variables['System.TeamProject'], 'internal') }}:
+ windowsPool: ${{ parameters.windowsPoolInternal }}
+ ${{ else }}:
+ windowsPool: ${{ parameters.windowsPoolPublic }}
targetFrameworkVersion: ${{ targetFrameworkVersion }}
windowsVersions: [ 'packaged', 'unpackaged' ]
skipProvisioning: true
diff --git a/eng/pipelines/ci-uitests.yml b/eng/pipelines/ci-uitests.yml
index 6a821cb21202..cb1526b6d4fd 100644
--- a/eng/pipelines/ci-uitests.yml
+++ b/eng/pipelines/ci-uitests.yml
@@ -62,7 +62,8 @@ parameters:
type: boolean
default: false
- - name: androidPool
+ # Internal pools (dnceng)
+ - name: androidPoolInternal
type: object
default:
name: MAUI
@@ -70,14 +71,54 @@ parameters:
demands:
- Agent.OSArchitecture -equals ARM64
- - name: androidPoolLinux
+ - name: androidPoolLinuxInternal
+ type: object
+ default:
+ name: NetCore1ESPool-Internal
+ demands:
+ - ImageOverride -equals 1ESPT-Ubuntu22.04
+
+ - name: iosPoolInternal
+ type: object
+ default:
+ name: MAUI
+ vmImage: MAUI
+
+ - name: windowsBuildPoolInternal
+ type: object
+ default:
+ name: NetCore1ESPool-Internal
+ demands:
+ - ImageOverride -equals 1es-windows-2022
+
+ - name: windowsPoolInternal
+ type: object
+ default:
+ name: NetCore1ESPool-Internal
+ demands:
+ - ImageOverride -equals 1es-windows-2022
+
+ - name: macosPoolInternal
+ type: object
+ default:
+ name: Azure Pipelines
+ vmImage: macOS-15
+
+ # Public pools (dnceng-public)
+ - name: androidPoolPublic
+ type: object
+ default:
+ name: MAUI
+ vmImage: MAUI
+
+ - name: androidPoolLinuxPublic
type: object
default:
name: MAUI-DNCENG
demands:
- ImageOverride -equals 1ESPT-Ubuntu22.04
- - name: iosPool
+ - name: iosPoolPublic
type: object
default:
name: MAUI
@@ -85,21 +126,21 @@ parameters:
demands:
- Agent.OSArchitecture -equals ARM64
- - name: windowsBuildPool
+ - name: windowsBuildPoolPublic
type: object
default:
name: NetCore-Public
demands:
- ImageOverride -equals 1es-windows-2022-open
- - name: windowsPool
+ - name: windowsPoolPublic
type: object
default:
name: NetCore-Public
demands:
- ImageOverride -equals 1es-windows-2022-open
- - name: macosPool
+ - name: macosPoolPublic
type: object
default:
name: Azure Pipelines
@@ -109,12 +150,21 @@ stages:
- template: common/ui-tests.yml
parameters:
- androidPool: ${{ parameters.androidPool }}
- androidLinuxPool: ${{ parameters.androidPoolLinux }}
- iosPool: ${{ parameters.iosPool }}
- windowsPool: ${{ parameters.windowsPool }}
- windowsBuildPool: ${{ parameters.windowsBuildPool }}
- macosPool: ${{ parameters.macosPool }}
+ # Select pools based on pipeline - internal vs public
+ ${{ if eq(variables['System.TeamProject'], 'internal') }}:
+ androidPool: ${{ parameters.androidPoolInternal }}
+ androidLinuxPool: ${{ parameters.androidPoolLinuxInternal }}
+ iosPool: ${{ parameters.iosPoolInternal }}
+ windowsPool: ${{ parameters.windowsPoolInternal }}
+ windowsBuildPool: ${{ parameters.windowsBuildPoolInternal }}
+ macosPool: ${{ parameters.macosPoolInternal }}
+ ${{ else }}:
+ androidPool: ${{ parameters.androidPoolPublic }}
+ androidLinuxPool: ${{ parameters.androidPoolLinuxPublic }}
+ iosPool: ${{ parameters.iosPoolPublic }}
+ windowsPool: ${{ parameters.windowsPoolPublic }}
+ windowsBuildPool: ${{ parameters.windowsBuildPoolPublic }}
+ macosPool: ${{ parameters.macosPoolPublic }}
# BuildNativeAOT is false by default, but true in devdiv environment
BuildNativeAOT: ${{ or(parameters.BuildNativeAOT, and(ne(variables['Build.Reason'], 'PullRequest'), eq(variables['System.TeamProject'], 'devdiv'))) }}
RunNativeAOT: ${{ parameters.RunNativeAOT }}
diff --git a/eng/pipelines/ci.yml b/eng/pipelines/ci.yml
index 939132f68ef1..fbeec182faec 100644
--- a/eng/pipelines/ci.yml
+++ b/eng/pipelines/ci.yml
@@ -94,6 +94,7 @@ parameters:
- ImageOverride -equals 1es-windows-2022-open
os: windows
+# Typically X64 pools but XCode 26.2 isn't available yet for the Azure Pipelines X64 Pools
- name: MacOSPool
type: object
default:
@@ -101,21 +102,33 @@ parameters:
vmImage: MAUI
os: macOS
label: macOS
+# Switch back to this once XCode 26.2 is available on Azure Pipelines
+# name: Azure Pipelines
+# vmImage: $(HostedMacImage)
+# os: macOS
+# label: macOS
# ARM64 macOS pool (Apple Silicon)
- name: MacOSPoolArm64
type: object
default:
- name: Azure Pipelines
- vmImage: macOS-15-arm64
+ name: MAUI
+ vmImage: MAUI
os: macOS
label: macOS-arm64
+# Switch back to this once XCode 26.2 is available on Azure Pipelines
+# name: Azure Pipelines
+# vmImage: macOS-15-arm64
+# os: macOS
+# label: macOS-arm64
# Condition for MacOSPool comparison lanes (non-ARM64)
-# Runs on: (non-PR on main/net*.0/release/*/inflight/*) OR (PR targeting net*.0/release/*/inflight/*)
+# Currently disabled - both pools use MAUI self-hosted since Xcode 26.2 isn't available on Azure Pipelines x64.
+# Re-enable once Azure Pipelines has Xcode 26.2 on x64 pools.
+# Original condition: or(and(ne(variables['Build.Reason'], 'PullRequest'), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), and(startsWith(variables['Build.SourceBranch'], 'refs/heads/net'), endsWith(variables['Build.SourceBranch'], '.0')), startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/inflight/'))), and(eq(variables['Build.Reason'], 'PullRequest'), or(and(startsWith(variables['System.PullRequest.TargetBranch'], 'net'), endsWith(variables['System.PullRequest.TargetBranch'], '.0')), startsWith(variables['System.PullRequest.TargetBranch'], 'release/'), startsWith(variables['System.PullRequest.TargetBranch'], 'inflight/'))))
- name: macOSPoolLaneCondition
type: string
- default: or(and(ne(variables['Build.Reason'], 'PullRequest'), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), and(startsWith(variables['Build.SourceBranch'], 'refs/heads/net'), endsWith(variables['Build.SourceBranch'], '.0')), startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/inflight/'))), and(eq(variables['Build.Reason'], 'PullRequest'), or(and(startsWith(variables['System.PullRequest.TargetBranch'], 'net'), endsWith(variables['System.PullRequest.TargetBranch'], '.0')), startsWith(variables['System.PullRequest.TargetBranch'], 'release/'), startsWith(variables['System.PullRequest.TargetBranch'], 'inflight/'))))
+ default: false
stages:
diff --git a/eng/pipelines/common/provision.yml b/eng/pipelines/common/provision.yml
index 4c82b903e4f9..0584e7f1e275 100644
--- a/eng/pipelines/common/provision.yml
+++ b/eng/pipelines/common/provision.yml
@@ -192,6 +192,17 @@ steps:
continueOnError: true
timeoutInMinutes: 30
+ # Also install iOS 18.5 simulator for integration tests that require it
+ - script: |
+ echo "Installing iOS 18.5 simulator runtime for integration tests..."
+ sudo xcodebuild -downloadPlatform iOS -buildVersion 18.5 || {
+ echo "Warning: Failed to install iOS 18.5 simulator. Tests requiring this version may fail."
+ }
+ displayName: Install iOS 18.5 Simulator (for integration tests)
+ condition: and(succeeded(), eq(variables['Agent.OS'], 'Darwin'))
+ continueOnError: true
+ timeoutInMinutes: 30
+
# Provision Additional Software
- ${{ if or(eq(variables['System.TeamProject'], 'DevDiv'), ne(parameters.skipProvisionator, true)) }}:
# Prepare macOS
diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18751.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18751.cs
index 7a565c955a5c..67d0fa430bae 100644
--- a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18751.cs
+++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18751.cs
@@ -1,4 +1,4 @@
-#if TEST_FAILS_ON_WINDOWS //related issues: https://github.com/dotnet/maui/issues/15994
+#if TEST_FAILS_ON_IOS && TEST_FAILS_ON_CATALYST && TEST_FAILS_ON_WINDOWS //related issues: https://github.com/dotnet/maui/issues/33507, https://github.com/dotnet/maui/issues/15994
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;
diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18896.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18896.cs
index 475420d26f16..65acc5141cd1 100644
--- a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18896.cs
+++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18896.cs
@@ -1,4 +1,4 @@
-#if TEST_FAILS_ON_IOS && TEST_FAILS_ON_CATALYST && TEST_FAILS_ON_WINDOWS//Related issues : https://github.com/dotnet/maui/issues/18811, https://github.com/dotnet/maui/issues/15994
+#if TEST_FAILS_ON_ANDROID && TEST_FAILS_ON_IOS && TEST_FAILS_ON_CATALYST && TEST_FAILS_ON_WINDOWS//Related issues : https://github.com/dotnet/maui/issues/33507, https://github.com/dotnet/maui/issues/18811, https://github.com/dotnet/maui/issues/15994
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;