diff --git a/Microsoft.Maui-dev.sln b/Microsoft.Maui-dev.sln index 35021b33fea4..03b88ee99e8e 100644 --- a/Microsoft.Maui-dev.sln +++ b/Microsoft.Maui-dev.sln @@ -205,6 +205,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Controls.Xaml.UnitTests.Int EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Controls.Xaml.UnitTests.InternalsHiddenAssembly", "src\Controls\tests\Xaml.UnitTests.InternalsHiddenAssembly\Controls.Xaml.UnitTests.InternalsHiddenAssembly.csproj", "{FB39FACE-BAF2-4F97-A249-E45BA63D77FE}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Controls.AppiumTests", "src\Controls\tests\UITests\Controls.AppiumTests.csproj", "{2A0CB35C-ED05-4FCB-91BC-21B288B749B1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtils.Appium", "src\TestUtils\src\TestUtils.Appium\TestUtils.Appium.csproj", "{FABB4FE3-AD90-479E-B7F1-BEF110181196}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtils.Appium.UITests", "src\TestUtils\src\TestUtils.Appium.UITests\TestUtils.Appium.UITests.csproj", "{E06CEFD4-237C-49F0-BE0F-C5F80AD8F64C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Controls.Sample.UITests", "src\Controls\samples\Controls.Sample.UITests\Controls.Sample.UITests.csproj", "{07C26A25-08C2-4C52-9574-1C33EC8E7919}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Maui.IntegrationTests", "src\TestUtils\src\Microsoft.Maui.IntegrationTests\Microsoft.Maui.IntegrationTests.csproj", "{A6976D43-B3A4-47AF-89D9-FA388B56B52B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -519,6 +529,27 @@ Global {FB39FACE-BAF2-4F97-A249-E45BA63D77FE}.Debug|Any CPU.Build.0 = Debug|Any CPU {FB39FACE-BAF2-4F97-A249-E45BA63D77FE}.Release|Any CPU.ActiveCfg = Release|Any CPU {FB39FACE-BAF2-4F97-A249-E45BA63D77FE}.Release|Any CPU.Build.0 = Release|Any CPU + {2A0CB35C-ED05-4FCB-91BC-21B288B749B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2A0CB35C-ED05-4FCB-91BC-21B288B749B1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A0CB35C-ED05-4FCB-91BC-21B288B749B1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A0CB35C-ED05-4FCB-91BC-21B288B749B1}.Release|Any CPU.Build.0 = Release|Any CPU + {FABB4FE3-AD90-479E-B7F1-BEF110181196}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FABB4FE3-AD90-479E-B7F1-BEF110181196}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FABB4FE3-AD90-479E-B7F1-BEF110181196}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FABB4FE3-AD90-479E-B7F1-BEF110181196}.Release|Any CPU.Build.0 = Release|Any CPU + {E06CEFD4-237C-49F0-BE0F-C5F80AD8F64C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E06CEFD4-237C-49F0-BE0F-C5F80AD8F64C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E06CEFD4-237C-49F0-BE0F-C5F80AD8F64C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E06CEFD4-237C-49F0-BE0F-C5F80AD8F64C}.Release|Any CPU.Build.0 = Release|Any CPU + {07C26A25-08C2-4C52-9574-1C33EC8E7919}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {07C26A25-08C2-4C52-9574-1C33EC8E7919}.Debug|Any CPU.Build.0 = Debug|Any CPU + {07C26A25-08C2-4C52-9574-1C33EC8E7919}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {07C26A25-08C2-4C52-9574-1C33EC8E7919}.Release|Any CPU.ActiveCfg = Release|Any CPU + {07C26A25-08C2-4C52-9574-1C33EC8E7919}.Release|Any CPU.Build.0 = Release|Any CPU + {A6976D43-B3A4-47AF-89D9-FA388B56B52B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A6976D43-B3A4-47AF-89D9-FA388B56B52B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A6976D43-B3A4-47AF-89D9-FA388B56B52B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A6976D43-B3A4-47AF-89D9-FA388B56B52B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -613,6 +644,11 @@ Global {B5F38A9E-1949-4779-8739-D682B09E0CB3} = {25D0D27A-C5FE-443D-8B65-D6C987F4A80E} {B5F38A9E-1949-4779-6666-D682B09E0CB3} = {25D0D27A-C5FE-443D-8B65-D6C987F4A80E} {FB39FACE-BAF2-4F97-A249-E45BA63D77FE} = {25D0D27A-C5FE-443D-8B65-D6C987F4A80E} + {2A0CB35C-ED05-4FCB-91BC-21B288B749B1} = {25D0D27A-C5FE-443D-8B65-D6C987F4A80E} + {FABB4FE3-AD90-479E-B7F1-BEF110181196} = {7AC28763-9C68-4BF9-A1BA-25CBFFD2D15C} + {E06CEFD4-237C-49F0-BE0F-C5F80AD8F64C} = {7AC28763-9C68-4BF9-A1BA-25CBFFD2D15C} + {07C26A25-08C2-4C52-9574-1C33EC8E7919} = {E1082E26-D700-4127-9329-66D673FD2D55} + {A6976D43-B3A4-47AF-89D9-FA388B56B52B} = {7AC28763-9C68-4BF9-A1BA-25CBFFD2D15C} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {0B8ABEAD-D2B5-4370-A187-62B5ABE4EE50} diff --git a/Microsoft.Maui-mac.slnf b/Microsoft.Maui-mac.slnf index 06a5535791d9..45047f123ade 100644 --- a/Microsoft.Maui-mac.slnf +++ b/Microsoft.Maui-mac.slnf @@ -11,6 +11,7 @@ "src\\Controls\\samples\\Controls.Sample.Profiling\\Maui.Controls.Sample.Profiling.csproj", "src\\Controls\\samples\\Controls.Sample.Sandbox\\Maui.Controls.Sample.Sandbox.csproj", "src\\Controls\\samples\\Controls.Sample\\Maui.Controls.Sample.csproj", + "src\\Controls\\samples\\Controls.Sample.UITests\\Controls.Sample.UITests.csproj", "src\\Controls\\src\\Build.Tasks\\Controls.Build.Tasks.csproj", "src\\Controls\\src\\Core.Design\\Controls.Core.Design.csproj", "src\\Controls\\src\\Core\\Controls.Core.csproj", @@ -21,6 +22,7 @@ "src\\Controls\\tests\\Core.UnitTests\\Controls.Core.UnitTests.csproj", "src\\Controls\\tests\\CustomAttributes\\Controls.CustomAttributes.csproj", "src\\Controls\\tests\\DeviceTests\\Controls.DeviceTests.csproj", + "src\\Controls\\tests\\UITests\\Controls.AppiumTests.csproj", "src\\Controls\\tests\\Xaml.UnitTests.ExternalAssembly\\Controls.Xaml.UnitTests.ExternalAssembly.csproj", "src\\Controls\\tests\\Xaml.UnitTests.InternalsVisibleAssembly\\Controls.Xaml.UnitTests.InternalsVisibleAssembly.csproj", "src\\Controls\\tests\\Xaml.UnitTests.InternalsHiddenAssembly\\Controls.Xaml.UnitTests.InternalsHiddenAssembly.csproj", @@ -48,6 +50,8 @@ "src\\TestUtils\\src\\DeviceTests.Runners\\TestUtils.DeviceTests.Runners.csproj", "src\\TestUtils\\src\\DeviceTests\\TestUtils.DeviceTests.csproj", "src\\TestUtils\\src\\TestUtils\\TestUtils.csproj", + "src\\TestUtils\\src\\TestUtils.Appium.UITests\\TestUtils.Appium.UITests.csproj", + "src\\TestUtils\\src\\TestUtils.Appium\\TestUtils.Appium.csproj", "src\\Workload\\Microsoft.Maui.Sdk\\Microsoft.Maui.Sdk.csproj", "src\\Workload\\Microsoft.NET.Sdk.Maui\\Microsoft.NET.Sdk.Maui.csproj" ] diff --git a/Microsoft.Maui-windows.slnf b/Microsoft.Maui-windows.slnf index 57e29b050cca..8ef944cf9f03 100644 --- a/Microsoft.Maui-windows.slnf +++ b/Microsoft.Maui-windows.slnf @@ -14,6 +14,7 @@ "src\\Controls\\Maps\\src\\Controls.Maps.csproj", "src\\Controls\\samples\\Controls.Sample.Profiling\\Maui.Controls.Sample.Profiling.csproj", "src\\Controls\\samples\\Controls.Sample.Sandbox\\Maui.Controls.Sample.Sandbox.csproj", + "src\\Controls\\samples\\Controls.Sample.UITests\\Controls.Sample.UITests.csproj", "src\\Controls\\samples\\Controls.Sample\\Maui.Controls.Sample.csproj", "src\\Controls\\src\\Build.Tasks\\Controls.Build.Tasks.csproj", "src\\Controls\\src\\Core.Design\\Controls.Core.Design.csproj", @@ -26,6 +27,7 @@ "src\\Controls\\tests\\Core.UnitTests\\Controls.Core.UnitTests.csproj", "src\\Controls\\tests\\CustomAttributes\\Controls.CustomAttributes.csproj", "src\\Controls\\tests\\DeviceTests\\Controls.DeviceTests.csproj", + "src\\Controls\\tests\\UITests\\Controls.AppiumTests.csproj", "src\\Controls\\tests\\Xaml.UnitTests.ExternalAssembly\\Controls.Xaml.UnitTests.ExternalAssembly.csproj", "src\\Controls\\tests\\Xaml.UnitTests.InternalsHiddenAssembly\\Controls.Xaml.UnitTests.InternalsHiddenAssembly.csproj", "src\\Controls\\tests\\Xaml.UnitTests.InternalsVisibleAssembly\\Controls.Xaml.UnitTests.InternalsVisibleAssembly.csproj", @@ -64,6 +66,9 @@ "src\\TestUtils\\src\\DeviceTests.Runners.SourceGen\\TestUtils.DeviceTests.Runners.SourceGen.csproj", "src\\TestUtils\\src\\DeviceTests.Runners\\TestUtils.DeviceTests.Runners.csproj", "src\\TestUtils\\src\\DeviceTests\\TestUtils.DeviceTests.csproj", + "src\\TestUtils\\src\\Microsoft.Maui.IntegrationTests\\Microsoft.Maui.IntegrationTests.csproj", + "src\\TestUtils\\src\\TestUtils.Appium.UITests\\TestUtils.Appium.UITests.csproj", + "src\\TestUtils\\src\\TestUtils.Appium\\TestUtils.Appium.csproj", "src\\TestUtils\\src\\TestUtils\\TestUtils.csproj", "src\\Workload\\Microsoft.Maui.Sdk\\Microsoft.Maui.Sdk.csproj", "src\\Workload\\Microsoft.NET.Sdk.Maui\\Microsoft.NET.Sdk.Maui.csproj" diff --git a/Microsoft.Maui.Samples.slnf b/Microsoft.Maui.Samples.slnf index 880d4bcd6cc6..1b03fe735ac9 100644 --- a/Microsoft.Maui.Samples.slnf +++ b/Microsoft.Maui.Samples.slnf @@ -4,7 +4,8 @@ "projects": [ "src\\BlazorWebView\\samples\\MauiRazorClassLibrarySample\\MauiRazorClassLibrarySample.csproj", "src\\Controls\\samples\\Controls.Sample.Sandbox\\Maui.Controls.Sample.Sandbox.csproj", + "src\\Controls\\samples\\Controls.Sample.UITests\\Controls.Sample.UITests.csproj", "src\\Controls\\samples\\Controls.Sample\\Maui.Controls.Sample.csproj" ] } -} +} \ No newline at end of file diff --git a/Microsoft.Maui.sln b/Microsoft.Maui.sln index 5f4f45f37f17..129ed8ad0030 100644 --- a/Microsoft.Maui.sln +++ b/Microsoft.Maui.sln @@ -245,6 +245,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.DeviceTests.Shared", " EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Graphics.DeviceTests", "src\Graphics\tests\DeviceTests\Graphics.DeviceTests.csproj", "{34969E49-FA6E-41BB-9813-5689BB14021E}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Controls.AppiumTests", "src\Controls\tests\UITests\Controls.AppiumTests.csproj", "{A23B108A-AB56-4692-B9DA-0E23602E3955}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestUtils.Appium", "src\TestUtils\src\TestUtils.Appium\TestUtils.Appium.csproj", "{EDADE060-6B61-4006-BB7D-CB7710F08E87}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestUtils.Appium.UITests", "src\TestUtils\src\TestUtils.Appium.UITests\TestUtils.Appium.UITests.csproj", "{0930F067-A388-4C9C-A249-653B74625A4E}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Compatibility.Core.UnitTests", "src\Compatibility\Core\tests\Compatibility.UnitTests\Compatibility.Core.UnitTests.csproj", "{13A1AFD2-78D3-4463-9977-C8B642BCE2E2}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Controls.Xaml.UnitTests.ExternalAssembly", "src\Controls\tests\Xaml.UnitTests.ExternalAssembly\Controls.Xaml.UnitTests.ExternalAssembly.csproj", "{F2ADA552-6328-4B2D-8D48-FCDD32C4AF60}" @@ -255,6 +261,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Maui.IntegrationT EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Controls.Xaml.UnitTests.InternalsHiddenAssembly", "src\Controls\tests\Xaml.UnitTests.InternalsHiddenAssembly\Controls.Xaml.UnitTests.InternalsHiddenAssembly.csproj", "{FB39FACE-BAF2-4F97-A249-E45BA63D77FE}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Controls.Sample.UITests", "src\Controls\samples\Controls.Sample.UITests\Controls.Sample.UITests.csproj", "{F39F75DC-671B-4649-8005-1929797B3217}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -619,6 +627,18 @@ Global {34969E49-FA6E-41BB-9813-5689BB14021E}.Release|Any CPU.ActiveCfg = Release|Any CPU {34969E49-FA6E-41BB-9813-5689BB14021E}.Release|Any CPU.Build.0 = Release|Any CPU {34969E49-FA6E-41BB-9813-5689BB14021E}.Release|Any CPU.Deploy.0 = Release|Any CPU + {A23B108A-AB56-4692-B9DA-0E23602E3955}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A23B108A-AB56-4692-B9DA-0E23602E3955}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A23B108A-AB56-4692-B9DA-0E23602E3955}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A23B108A-AB56-4692-B9DA-0E23602E3955}.Release|Any CPU.Build.0 = Release|Any CPU + {EDADE060-6B61-4006-BB7D-CB7710F08E87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EDADE060-6B61-4006-BB7D-CB7710F08E87}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EDADE060-6B61-4006-BB7D-CB7710F08E87}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EDADE060-6B61-4006-BB7D-CB7710F08E87}.Release|Any CPU.Build.0 = Release|Any CPU + {0930F067-A388-4C9C-A249-653B74625A4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0930F067-A388-4C9C-A249-653B74625A4E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0930F067-A388-4C9C-A249-653B74625A4E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0930F067-A388-4C9C-A249-653B74625A4E}.Release|Any CPU.Build.0 = Release|Any CPU {13A1AFD2-78D3-4463-9977-C8B642BCE2E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {13A1AFD2-78D3-4463-9977-C8B642BCE2E2}.Debug|Any CPU.Build.0 = Debug|Any CPU {13A1AFD2-78D3-4463-9977-C8B642BCE2E2}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -639,6 +659,10 @@ Global {FB39FACE-BAF2-4F97-A249-E45BA63D77FE}.Debug|Any CPU.Build.0 = Debug|Any CPU {FB39FACE-BAF2-4F97-A249-E45BA63D77FE}.Release|Any CPU.ActiveCfg = Release|Any CPU {FB39FACE-BAF2-4F97-A249-E45BA63D77FE}.Release|Any CPU.Build.0 = Release|Any CPU + {F39F75DC-671B-4649-8005-1929797B3217}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F39F75DC-671B-4649-8005-1929797B3217}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F39F75DC-671B-4649-8005-1929797B3217}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F39F75DC-671B-4649-8005-1929797B3217}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -752,11 +776,15 @@ Global {4A6930AE-B67C-4D29-B1A8-ED9EB7F923A7} = {50C758FE-4E10-409A-94F5-A75480960864} {66CC98E3-6A1A-4C44-A23C-B575E82106EC} = {C564DDD6-DE79-45CD-88EA-3F690481572A} {34969E49-FA6E-41BB-9813-5689BB14021E} = {936C47A9-A7EA-4FBD-8733-CED1D4100E69} + {A23B108A-AB56-4692-B9DA-0E23602E3955} = {E1082E26-D700-4127-9329-66D673FD2D55} + {EDADE060-6B61-4006-BB7D-CB7710F08E87} = {7AC28763-9C68-4BF9-A1BA-25CBFFD2D15C} + {0930F067-A388-4C9C-A249-653B74625A4E} = {7AC28763-9C68-4BF9-A1BA-25CBFFD2D15C} {13A1AFD2-78D3-4463-9977-C8B642BCE2E2} = {85EBD2BA-EA5A-4B1F-AF16-81FBD58579DF} {F2ADA552-6328-4B2D-8D48-FCDD32C4AF60} = {25D0D27A-C5FE-443D-8B65-D6C987F4A80E} {B5F38A9E-1949-4779-6666-D682B09E0CB3} = {25D0D27A-C5FE-443D-8B65-D6C987F4A80E} {1C899C94-8744-4E2A-8E23-1660393236FD} = {7AC28763-9C68-4BF9-A1BA-25CBFFD2D15C} {FB39FACE-BAF2-4F97-A249-E45BA63D77FE} = {25D0D27A-C5FE-443D-8B65-D6C987F4A80E} + {F39F75DC-671B-4649-8005-1929797B3217} = {E1082E26-D700-4127-9329-66D673FD2D55} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {0B8ABEAD-D2B5-4370-A187-62B5ABE4EE50} diff --git a/eng/cake/dotnet.cake b/eng/cake/dotnet.cake index 5dd680bbd039..b1857cef208f 100644 --- a/eng/cake/dotnet.cake +++ b/eng/cake/dotnet.cake @@ -9,6 +9,7 @@ string MSBuildExe = Argument("msbuild", EnvironmentVariable("MSBUILD_EXE", "")); string nugetSource = Argument("nugetsource", ""); string TestTFM = Argument("testtfm", ""); +var useNuget = Argument("usenuget", true); if (TestTFM == "default") TestTFM = ""; @@ -143,11 +144,17 @@ Task("dotnet-samples") { var tempDir = PrepareSeparateBuildContext("samplesTest"); - RunMSBuildWithDotNet("./Microsoft.Maui.Samples.slnf", new Dictionary { - ["UseWorkload"] = "true", - // ["GenerateAppxPackageOnBuild"] = "true", - ["RestoreConfigFile"] = tempDir.CombineWithFilePath("NuGet.config").FullPath, - }, binlogPrefix: "sample-"); + var properties = new Dictionary(); + + if(useNuget) + { + properties = new Dictionary { + ["UseWorkload"] = "true", + // ["GenerateAppxPackageOnBuild"] = "true", + ["RestoreConfigFile"] = tempDir.CombineWithFilePath("NuGet.config").FullPath, + }; + } + RunMSBuildWithDotNet("./Microsoft.Maui.Samples.slnf", properties, binlogPrefix: "sample-"); }); Task("dotnet-samples-test") diff --git a/eng/cake/helpers.cake b/eng/cake/helpers.cake index 628bec7ccfa5..245d905ff9db 100644 --- a/eng/cake/helpers.cake +++ b/eng/cake/helpers.cake @@ -121,3 +121,40 @@ bool IsTarget(string target) => bool TargetStartsWith(string target) => Argument("target", "Default").StartsWith(target, StringComparison.InvariantCultureIgnoreCase); + +void RunTestWithLocalDotNet(string csproj, string configuration, string dotnetPath = null, Dictionary argsExtra = null, bool noBuild = false) +{ + var name = System.IO.Path.GetFileNameWithoutExtension(csproj); + var binlog = $"{GetLogDirectory()}/{name}-{configuration}.binlog"; + var results = $"{name}-{configuration}.trx"; + + Information("Run Test binlog: {0}", binlog); + + var settings = new DotNetCoreTestSettings + { + Configuration = configuration, + NoBuild = noBuild, + Logger = $"trx;LogFileName={results}", + ResultsDirectory = GetTestResultsDirectory(), + //Verbosity = Cake.Common.Tools.DotNetCore.DotNetCoreVerbosity.Diagnostic, + ArgumentCustomization = args => + { + args.Append($"-bl:{binlog}"); + if(argsExtra != null) + { + foreach(var prop in argsExtra) + { + args.Append($"/p:{prop.Key}={prop.Value}"); + } + } + return args; + } + }; + + if(!string.IsNullOrEmpty(dotnetPath)) + { + settings.ToolPath = dotnetPath; + } + + DotNetCoreTest(csproj, settings); +} diff --git a/eng/devices/android.cake b/eng/devices/android.cake index a155eafea576..dd4f0c05bafa 100644 --- a/eng/devices/android.cake +++ b/eng/devices/android.cake @@ -3,25 +3,30 @@ #load "../cake/helpers.cake" string TARGET = Argument("target", "Test"); +const string defaultVersion = "30"; // required FilePath PROJECT = Argument("project", EnvironmentVariable("ANDROID_TEST_PROJECT") ?? ""); -string TEST_DEVICE = Argument("device", EnvironmentVariable("ANDROID_TEST_DEVICE") ?? "android-emulator-32_30"); +string TEST_DEVICE = Argument("device", EnvironmentVariable("ANDROID_TEST_DEVICE") ?? $"android-emulator-32_{defaultVersion}"); string DEVICE_NAME = Argument("skin", EnvironmentVariable("ANDROID_TEST_SKIN") ?? "Nexus 5X"); // optional +var localDotnet = GetBuildVariable("workloads", "local") == "local"; var USE_DOTNET = Argument("dotnet", true); var DOTNET_PATH = Argument("dotnet-path", EnvironmentVariable("DOTNET_PATH")); var TARGET_FRAMEWORK = Argument("tfm", EnvironmentVariable("TARGET_FRAMEWORK") ?? (USE_DOTNET ? "net7.0-android" : "")); var BINLOG_ARG = Argument("binlog", EnvironmentVariable("ANDROID_TEST_BINLOG") ?? ""); DirectoryPath BINLOG_DIR = string.IsNullOrEmpty(BINLOG_ARG) && !string.IsNullOrEmpty(PROJECT.FullPath) ? PROJECT.GetDirectory() : BINLOG_ARG; var TEST_APP = Argument("app", EnvironmentVariable("ANDROID_TEST_APP") ?? ""); +FilePath TEST_APP_PROJECT = Argument("appproject", EnvironmentVariable("ANDROID_TEST_APP_PROJECT") ?? ""); var TEST_APP_PACKAGE_NAME = Argument("package", EnvironmentVariable("ANDROID_TEST_APP_PACKAGE_NAME") ?? ""); var TEST_APP_INSTRUMENTATION = Argument("instrumentation", EnvironmentVariable("ANDROID_TEST_APP_INSTRUMENTATION") ?? ""); var TEST_RESULTS = Argument("results", EnvironmentVariable("ANDROID_TEST_RESULTS") ?? ""); +var androidVersion = Argument("apiversion", EnvironmentVariable("ANDROID_PLATFORM_VERSION") ?? defaultVersion); + // other -string CONFIGURATION = "Debug"; // needs to be debug so unit tests get discovered +string CONFIGURATION = Argument("configuration", "Debug"); string ANDROID_AVD = "DEVICE_TESTS_EMULATOR"; string DEVICE_ID = ""; string DEVICE_ARCH = ""; @@ -122,7 +127,7 @@ Teardown(context => if (emulatorProcess == null || !DEVICE_BOOT || TARGET.ToLower() == "boot") return; - // stop and cleanup the emulator + //stop and cleanup the emulator AdbEmuKill(adbSettings); System.Threading.Thread.Sleep(5000); @@ -189,6 +194,7 @@ Task("Test") if (string.IsNullOrEmpty(PROJECT.FullPath)) throw new Exception("If no app was specified, an app must be provided."); var binDir = PROJECT.GetDirectory().Combine("bin").Combine(CONFIGURATION + "/" + TARGET_FRAMEWORK).FullPath; + Information("BinDir: {0}", binDir); var apps = GetFiles(binDir + "/*-Signed.apk"); if (apps.Any()) { TEST_APP = apps.FirstOrDefault().FullPath; @@ -280,4 +286,93 @@ Task("Test") } }); +Task("uitest") + .Does(() => +{ + if (string.IsNullOrEmpty(TEST_APP)) { + if (string.IsNullOrEmpty(TEST_APP_PROJECT.FullPath)) + throw new Exception("If no app was specified, an app must be provided."); + + var binFolder = TEST_APP_PROJECT.GetDirectory().Combine("bin"); + Information("Test app bin folder {0}", binFolder); + var binDir = binFolder.Combine("Release/net7.0-android").FullPath; + var apps = GetFiles(binDir + "/*-Signed.apk"); + if (apps.Any()) { + TEST_APP = apps.FirstOrDefault().FullPath; + } else { + apps = GetFiles(binDir + "/*.apk"); + TEST_APP = apps.First().FullPath; + } + } + if (string.IsNullOrEmpty(TEST_APP_PACKAGE_NAME)) { + var appFile = (FilePath)TEST_APP; + appFile = appFile.GetFilenameWithoutExtension(); + TEST_APP_PACKAGE_NAME = appFile.FullPath.Replace("-Signed", ""); + } + if (string.IsNullOrEmpty(TEST_APP_INSTRUMENTATION)) { + TEST_APP_INSTRUMENTATION = TEST_APP_PACKAGE_NAME + ".TestInstrumentation"; + } + if (string.IsNullOrEmpty(TEST_RESULTS)) { + TEST_RESULTS = TEST_APP + "-results"; + } + + Information("Test App: {0}", TEST_APP); + Information("Test App Package Name: {0}", TEST_APP_PACKAGE_NAME); + Information("Test App Instrumentation: {0}", TEST_APP_INSTRUMENTATION); + Information("Test Results Directory: {0}", TEST_RESULTS); + Information("Test project: {0}", PROJECT); + + CleanDirectories(TEST_RESULTS); + + if (DEVICE_BOOT_WAIT) { + Information("Waiting for the emulator to finish booting..."); + + // wait for it to finish booting (10 mins) + var waited = 0; + var total = 60 * 10; + while (AdbShell("getprop sys.boot_completed", adbSettings).FirstOrDefault() != "1") { + System.Threading.Thread.Sleep(1000); + Information("Wating {0}/{1} seconds for the emulator to boot up.", waited, total); + if (waited++ > total) + break; + } + Information("Waited {0} seconds for the emulator to boot up.", waited); + } + + Information("Setting the ADB properties..."); + var lines = AdbShell("setprop debug.mono.log default,mono_log_level=debug,mono_log_mask=all", adbSettings); + Information("{0}", string.Join("\n", lines)); + lines = AdbShell("getprop debug.mono.log", adbSettings); + Information("{0}", string.Join("\n", lines)); + + //install apk on the emulator + Information("Install with xharness: {0}",TEST_APP); + var settings = new DotNetCoreToolSettings { + DiagnosticOutput = true, + ArgumentCustomization = args=>args.Append("run xharness android install " + + $"--app=\"{TEST_APP}\" " + + $"--package-name=\"{TEST_APP_PACKAGE_NAME}\" " + + $"--output-directory=\"{TEST_RESULTS}\" " + + $"--verbosity=\"Debug\" ") + }; + DotNetCoreTool("tool", settings); + + //we need to build tests first to pass ExtraDefineConstants + Information("Build UITests project {0}", PROJECT.FullPath); + var name = System.IO.Path.GetFileNameWithoutExtension(PROJECT.FullPath); + var binlog = $"{BINLOG_DIR}/{name}-{CONFIGURATION}-android.binlog"; + DotNetCoreBuild(PROJECT.FullPath, new DotNetCoreBuildSettings { + Configuration = CONFIGURATION, + ArgumentCustomization = args => args + .Append("/p:ExtraDefineConstants=ANDROID") + .Append("/bl:" + binlog), + ToolPath = DOTNET_PATH, + }); + + SetEnvironmentVariable("APPIUM_LOG_FILE", $"{BINLOG_ARG}/appium_android.log"); + + Information("Run UITests project {0}",PROJECT.FullPath); + RunTestWithLocalDotNet(PROJECT.FullPath, CONFIGURATION, noBuild: true); +}); + RunTarget(TARGET); \ No newline at end of file diff --git a/eng/devices/catalyst.cake b/eng/devices/catalyst.cake new file mode 100644 index 000000000000..c466d5cc1012 --- /dev/null +++ b/eng/devices/catalyst.cake @@ -0,0 +1,97 @@ +#addin nuget:?package=Cake.AppleSimulator&version=0.2.0 +#load "../cake/helpers.cake" + +string TARGET = Argument("target", "Test"); + +const string defaultVersion = "14.4"; + +// required +FilePath PROJECT = Argument("project", EnvironmentVariable("MAC_TEST_PROJECT") ?? ""); +string TEST_DEVICE = Argument("device", EnvironmentVariable("MAC_TEST_DEVICE") ?? $"ios-simulator-64_{defaultVersion}"); // comma separated in the form -[-<32|64>][_] (eg: ios-simulator-64_13.4,[...]) + +// optional +var localDotnet = GetBuildVariable("workloads", "local") == "local"; +var DOTNET_PATH = Argument("dotnet-path", EnvironmentVariable("DOTNET_PATH")); +var TARGET_FRAMEWORK = Argument("tfm", EnvironmentVariable("TARGET_FRAMEWORK") ?? "net7.0-maccatalyst"); +var BINLOG_ARG = Argument("binlog", EnvironmentVariable("IOS_TEST_BINLOG") ?? ""); +DirectoryPath BINLOG_DIR = string.IsNullOrEmpty(BINLOG_ARG) && !string.IsNullOrEmpty(PROJECT.FullPath) ? PROJECT.GetDirectory() : BINLOG_ARG; +var TEST_APP = Argument("app", EnvironmentVariable("MAC_TEST_APP") ?? ""); +FilePath TEST_APP_PROJECT = Argument("appproject", EnvironmentVariable("MAC_TEST_APP_PROJECT") ?? ""); +var TEST_RESULTS = Argument("results", EnvironmentVariable("MAC_TEST_RESULTS") ?? ""); + +// other +string PLATFORM = "mac"; +string DOTNET_PLATFORM = "maccatalyst-x64"; +string CONFIGURATION = Argument("configuration", "Release"); +bool DEVICE_CLEANUP = Argument("cleanup", true); + +Information("Project File: {0}", PROJECT); +Information("Build Binary Log (binlog): {0}", BINLOG_DIR); +Information("Build Platform: {0}", PLATFORM); +Information("Build Configuration: {0}", CONFIGURATION); + +Setup(context => +{ + Cleanup(); +}); + +Teardown(context => +{ + Cleanup(); +}); + +void Cleanup() +{ + if (!DEVICE_CLEANUP) + return; +} + +Task("Cleanup"); + +Task("uitest") + .Does(() => +{ + if (string.IsNullOrEmpty(TEST_APP) ) { + if (string.IsNullOrEmpty(TEST_APP_PROJECT.FullPath)) + throw new Exception("If no app was specified, an app must be provided."); + var binDir = TEST_APP_PROJECT.GetDirectory().Combine("bin").Combine(CONFIGURATION + "/" + TARGET_FRAMEWORK).Combine(DOTNET_PLATFORM).FullPath; + Information("BinDir: {0}", binDir); + var apps = GetDirectories(binDir + "/*.app"); + TEST_APP = apps.First().FullPath; + } + if (string.IsNullOrEmpty(TEST_RESULTS)) { + TEST_RESULTS = TEST_APP + "-results"; + } + + Information("Test Device: {0}", TEST_DEVICE); + Information("Test App Project: {0}", TEST_APP_PROJECT); + Information("Test App: {0}", TEST_APP); + Information("Test Results Directory: {0}", TEST_RESULTS); + + CleanDirectories(TEST_RESULTS); + + Information("Run App project {0}",TEST_APP_PROJECT.FullPath); + DotNetCoreBuild(TEST_APP_PROJECT.FullPath, new DotNetCoreBuildSettings { + Configuration = CONFIGURATION, + ArgumentCustomization = args => args + .Append($"-f {TARGET_FRAMEWORK}") + .Append("-t:Run") + }); + + Information("Build UITests project {0}",PROJECT.FullPath); + var name = System.IO.Path.GetFileNameWithoutExtension(PROJECT.FullPath); + var binlog = $"{BINLOG_DIR}/{name}-{CONFIGURATION}-mac.binlog"; + DotNetCoreBuild(PROJECT.FullPath, new DotNetCoreBuildSettings { + Configuration = CONFIGURATION, + ArgumentCustomization = args => args + .Append("/p:ExtraDefineConstants=MACUITEST") + .Append("/bl:" + binlog) + }); + + SetEnvironmentVariable("APPIUM_LOG_FILE", $"{BINLOG_ARG}/appium_mac.log"); + + Information("Run UITests project {0}",PROJECT.FullPath); + RunTestWithLocalDotNet(PROJECT.FullPath, CONFIGURATION, noBuild: true); +}); + +RunTarget(TARGET); diff --git a/eng/devices/ios.cake b/eng/devices/ios.cake index fc34fc519480..cf3d0c1e4833 100644 --- a/eng/devices/ios.cake +++ b/eng/devices/ios.cake @@ -3,23 +3,31 @@ string TARGET = Argument("target", "Test"); +const string defaultVersion = "16.2"; + // required FilePath PROJECT = Argument("project", EnvironmentVariable("IOS_TEST_PROJECT") ?? ""); -string TEST_DEVICE = Argument("device", EnvironmentVariable("IOS_TEST_DEVICE") ?? "ios-simulator-64_14.4"); // comma separated in the form -[-<32|64>][_] (eg: ios-simulator-64_13.4,[...]) +string TEST_DEVICE = Argument("device", EnvironmentVariable("IOS_TEST_DEVICE") ?? $"ios-simulator-64_{defaultVersion}"); // comma separated in the form -[-<32|64>][_] (eg: ios-simulator-64_13.4,[...]) // optional +var localDotnet = GetBuildVariable("workloads", "local") == "local"; var USE_DOTNET = Argument("dotnet", true); var DOTNET_PATH = Argument("dotnet-path", EnvironmentVariable("DOTNET_PATH")); var TARGET_FRAMEWORK = Argument("tfm", EnvironmentVariable("TARGET_FRAMEWORK") ?? (USE_DOTNET ? "net7.0-ios" : "")); var BINLOG_ARG = Argument("binlog", EnvironmentVariable("IOS_TEST_BINLOG") ?? ""); DirectoryPath BINLOG_DIR = string.IsNullOrEmpty(BINLOG_ARG) && !string.IsNullOrEmpty(PROJECT.FullPath) ? PROJECT.GetDirectory() : BINLOG_ARG; var TEST_APP = Argument("app", EnvironmentVariable("IOS_TEST_APP") ?? ""); +FilePath TEST_APP_PROJECT = Argument("appproject", EnvironmentVariable("IOS_TEST_APP_PROJECT") ?? ""); var TEST_RESULTS = Argument("results", EnvironmentVariable("IOS_TEST_RESULTS") ?? ""); +//these are for appium iOS UITests +var udid = Argument("udid", EnvironmentVariable("IOS_SIMULATOR_UDID") ?? ""); +var iosVersion = Argument("apiversion", EnvironmentVariable("IOS_PLATFORM_VERSION") ?? defaultVersion); + // other string PLATFORM = TEST_DEVICE.ToLower().Contains("simulator") ? "iPhoneSimulator" : "iPhone"; string DOTNET_PLATFORM = TEST_DEVICE.ToLower().Contains("simulator") ? "iossimulator-x64" : "ios-x64"; -string CONFIGURATION = "Release"; +string CONFIGURATION = Argument("configuration", "Debug"); bool DEVICE_CLEANUP = Argument("cleanup", true); Information("Project File: {0}", PROJECT); @@ -191,4 +199,69 @@ Task("Test") } }); +Task("uitest") + .Does(() => +{ + if (string.IsNullOrEmpty(TEST_APP) ) { + if (string.IsNullOrEmpty(TEST_APP_PROJECT.FullPath)) + throw new Exception("If no app was specified, an app must be provided."); + var binDir = USE_DOTNET + ? TEST_APP_PROJECT.GetDirectory().Combine("bin").Combine(CONFIGURATION + "/" + TARGET_FRAMEWORK).Combine(DOTNET_PLATFORM).FullPath + : TEST_APP_PROJECT.GetDirectory().Combine("bin").Combine(PLATFORM).Combine(CONFIGURATION).FullPath; + Information("BinDir: {0}", binDir); + var apps = GetDirectories(binDir + "/*.app"); + TEST_APP = apps.First().FullPath; + } + if (string.IsNullOrEmpty(TEST_RESULTS)) { + TEST_RESULTS = TEST_APP + "-results"; + } + + Information("Test Device: {0}", TEST_DEVICE); + Information("Test App: {0}", TEST_APP); + Information("Test Results Directory: {0}", TEST_RESULTS); + + CleanDirectories(TEST_RESULTS); + + Information("Install with xharness: {0}",TEST_APP); + var settings = new DotNetCoreToolSettings { + DiagnosticOutput = true, + ArgumentCustomization = args => args.Append("run xharness apple install " + + $"--app=\"{TEST_APP}\" " + + $"--targets=\"{TEST_DEVICE}\" " + + $"--output-directory=\"{TEST_RESULTS}\" " + + $"--verbosity=\"Debug\" ") + }; + + try { + DotNetCoreTool("tool", settings); + } finally { + + var sims = ListAppleSimulators(); + var xharness = sims.Where(s => s.Name.Contains("XHarness")).ToArray(); + var simXH = xharness.First(); + Information("The emulator to run tests: {0} {1}", simXH.Name, simXH.UDID); + Information("The platform version to run tests: {0}", iosVersion); + SetEnvironmentVariable("IOS_SIMULATOR_UDID",simXH.UDID); + SetEnvironmentVariable("IOS_PLATFORM_VERSION", iosVersion); + + } + + //we need to build tests first to pass ExtraDefineConstants + Information("Build UITests project {0}", PROJECT.FullPath); + var name = System.IO.Path.GetFileNameWithoutExtension(PROJECT.FullPath); + var binlog = $"{BINLOG_DIR}/{name}-{CONFIGURATION}-ios.binlog"; + DotNetCoreBuild(PROJECT.FullPath, new DotNetCoreBuildSettings { + Configuration = CONFIGURATION, + ArgumentCustomization = args => args + .Append("/p:ExtraDefineConstants=IOSUITEST") + .Append("/bl:" + binlog), + ToolPath = DOTNET_PATH, + }); + + SetEnvironmentVariable("APPIUM_LOG_FILE", $"{BINLOG_ARG}/appium_ios.log"); + + Information("Run UITests project {0}",PROJECT.FullPath); + RunTestWithLocalDotNet(PROJECT.FullPath, CONFIGURATION, noBuild: true); +}); + RunTarget(TARGET); diff --git a/eng/devices/windows.cake b/eng/devices/windows.cake new file mode 100644 index 000000000000..ff4c32270821 --- /dev/null +++ b/eng/devices/windows.cake @@ -0,0 +1,105 @@ +#addin nuget:?package=Cake.AppleSimulator&version=0.2.0 +#load "../cake/helpers.cake" + +string TARGET = Argument("target", "Test"); + +const string defaultVersion = "10.0.19041"; + +// required +FilePath PROJECT = Argument("project", EnvironmentVariable("WINDOWS_TEST_PROJECT") ?? ""); +string TEST_DEVICE = Argument("device", EnvironmentVariable("WINDOWS_TEST_DEVICE") ?? $""); + +// optional +var localDotnet = GetBuildVariable("workloads", "local") == "local"; +var DOTNET_PATH = Argument("dotnet-path", EnvironmentVariable("DOTNET_PATH")); +var TARGET_FRAMEWORK = Argument("tfm", EnvironmentVariable("TARGET_FRAMEWORK") ?? $"net7.0-windows{defaultVersion}"); +var BINLOG_ARG = Argument("binlog", EnvironmentVariable("WINDOWS_TEST_BINLOG") ?? ""); +DirectoryPath BINLOG_DIR = string.IsNullOrEmpty(BINLOG_ARG) && !string.IsNullOrEmpty(PROJECT.FullPath) ? PROJECT.GetDirectory() : BINLOG_ARG; +var TEST_APP = Argument("app", EnvironmentVariable("WINDOWS_TEST_APP") ?? ""); +FilePath TEST_APP_PROJECT = Argument("appproject", EnvironmentVariable("WINDOWS_TEST_APP_PROJECT") ?? ""); +var TEST_RESULTS = Argument("results", EnvironmentVariable("MAC_TEST_RESULTS") ?? ""); +string CONFIGURATION = Argument("configuration", "Debug"); + +var windowsVersion = Argument("apiversion", EnvironmentVariable("WINDOWS_PLATFORM_VERSION") ?? defaultVersion); + +// other +string PLATFORM = "windows"; +string DOTNET_PLATFORM = $"win10-x64"; +bool DEVICE_CLEANUP = Argument("cleanup", true); + +Information("Project File: {0}", PROJECT); +Information("Build Binary Log (binlog): {0}", BINLOG_DIR); +Information("Build Platform: {0}", PLATFORM); +Information("Build Configuration: {0}", CONFIGURATION); + +Information("Windows version: {0}", windowsVersion); + +Setup(context => +{ + Cleanup(); +}); + +Teardown(context => +{ + Cleanup(); +}); + +void Cleanup() +{ + if (!DEVICE_CLEANUP) + return; +} + +Task("Cleanup"); + +Task("uitest") + .Does(() => +{ + if (string.IsNullOrEmpty(TEST_APP) ) { + if (string.IsNullOrEmpty(TEST_APP_PROJECT.FullPath)) + throw new Exception("If no app was specified, an app must be provided."); + var binDir = TEST_APP_PROJECT.GetDirectory().Combine("bin").Combine(CONFIGURATION + "/" + $"net7.0-windows{windowsVersion}").Combine(DOTNET_PLATFORM).FullPath; + Information("BinDir: {0}", binDir); + var apps = GetFiles(binDir + "/*.exe").Where(c => !c.FullPath.EndsWith("createdump.exe")); + TEST_APP = apps.First().FullPath; + } + if (string.IsNullOrEmpty(TEST_RESULTS)) { + TEST_RESULTS = TEST_APP + "-results"; + } + + Information("Test Device: {0}", TEST_DEVICE); + Information("Test App: {0}", TEST_APP); + Information("Test Results Directory: {0}", TEST_RESULTS); + + CleanDirectories(TEST_RESULTS); + + Information("Build UITests project {0}",PROJECT.FullPath); + var name = System.IO.Path.GetFileNameWithoutExtension(PROJECT.FullPath); + var binlog = $"{BINLOG_DIR}/{name}-{CONFIGURATION}-windows.binlog"; + + var dd = MakeAbsolute(Directory("../../bin/dotnet/")); + Information("DOTNET_PATH: {0}", dd); + + var toolPath = $"{dd}/dotnet.exe"; + + Information("toolPath: {0}", toolPath); + + SetDotNetEnvironmentVariables(dd.FullPath); + + DotNetCoreBuild(PROJECT.FullPath, new DotNetCoreBuildSettings { + Configuration = CONFIGURATION, + ArgumentCustomization = args => args + .Append("/p:ExtraDefineConstants=WINTEST") + .Append("/bl:" + binlog) + .Append("/maxcpucount:1"), + ToolPath = toolPath, + }); + + SetEnvironmentVariable("WINDOWS_APP_PATH", TEST_APP); + SetEnvironmentVariable("APPIUM_LOG_FILE", $"{BINLOG_ARG}/appium_windows.log"); + + Information("Run UITests project {0}",PROJECT.FullPath); + RunTestWithLocalDotNet(PROJECT.FullPath, CONFIGURATION, toolPath, noBuild: true); +}); + +RunTarget(TARGET); diff --git a/eng/pipelines/common/ui-tests-steps.yml b/eng/pipelines/common/ui-tests-steps.yml new file mode 100644 index 000000000000..380587c2490a --- /dev/null +++ b/eng/pipelines/common/ui-tests-steps.yml @@ -0,0 +1,109 @@ +parameters: + platform: '' # [ android, ios, windows, catalyst ] + path: '' # path to csproj + device: '' # the xharness device to use + cakeArgs: '' # additional cake args + app: '' #path to app to test + version: '' #the iOS version' + provisionatorChannel: 'latest' + agentPoolAccessToken: '' + configuration : "Release" + +steps: + + - template: provision.yml + parameters: + ${{ if eq(parameters.platform, 'windows') }}: + platform: windows + skipProvisioning: true + ${{ if ne(parameters.platform, 'windows') }}: + platform: macos + skipProvisioning: false + skipXcode: false + + provisionatorChannel: ${{ parameters.provisionatorChannel }} + + - task: PowerShell@2 + condition: ne('${{ parameters.platform }}' , 'windows') + inputs: + targetType: 'inline' + script: | + defaults write -g NSAutomaticCapitalizationEnabled -bool false + defaults write -g NSAutomaticTextCompletionEnabled -bool false + defaults write -g NSAutomaticSpellingCorrectionEnabled -bool false + displayName: "Modify defaults" + continueOnError: true + + - task: NodeTool@0 + inputs: + versionSpec: "18.13.0" + displayName: "Install node" + + - task: PowerShell@2 + inputs: + targetType: 'inline' + script: | + node -v + npm install -g appium@2.0.0-beta.61 + appium -v + $x = appium driver list --installed --json | ConvertFrom-Json + if(!$x.windows) + { + appium driver install --source=npm appium-windows-driver + } + if(!$x.uiautomator2) + { + appium driver install uiautomator2 + } + if(!$x.xcuitest) + { + appium driver install xcuitest + } + if(!$x.mac2) + { + appium driver install mac2 + } + displayName: "Install Appium" + continueOnError: true + + - pwsh: ./build.ps1 --target=dotnet --configuration="${{ parameters.configuration }}" --verbosity=diagnostic + displayName: 'Install .NET' + retryCountOnTaskFailure: 3 + env: + DOTNET_TOKEN: $(dotnetbuilds-internal-container-read-token) + PRIVATE_BUILD: $(PrivateBuild) + + - pwsh: echo "##vso[task.prependpath]$(DotNet.Dir)" + displayName: 'Add .NET to PATH' + + - pwsh: ./build.ps1 --target=dotnet-buildtasks --configuration="${{ parameters.configuration }}" + displayName: 'Build the MSBuild Tasks' + + - pwsh: ./build.ps1 --target=dotnet-samples --configuration="${{ parameters.configuration }}" --${{ parameters.platform }} --verbosity=diagnostic --usenuget=false + displayName: 'Build the samples' + + # - bash: | + # sudo xcode-select --reset + # displayName: 'XCode reset' + # condition: ne('${{ parameters.platform }}' , 'windows') + + - pwsh: ./build.ps1 -Script eng/devices/${{ parameters.platform }}.cake --target=uitest --project="${{ parameters.path }}" --appproject="${{ parameters.app }}" --device="${{ parameters.device }}" --apiversion="${{ parameters.version }}" --configuration="${{ parameters.configuration }}" --results="$(TestResultsDirectory)" --binlog="$(LogDirectory)" ${{ parameters.cakeArgs }} --verbosity=diagnostic + displayName: $(Agent.JobName) + retryCountOnTaskFailure: 2 + + - task: PublishTestResults@2 + displayName: Publish the $(System.PhaseName) test results + condition: always() + inputs: + testResultsFormat: VSTest + testResultsFiles: '$(TestResultsDirectory)/*.trx' + testRunTitle: '$(System.PhaseName)' + + - task: PublishBuildArtifacts@1 + condition: always() + displayName: publish artifacts + + # This must always be placed as the last step in the job + - template: agent-rebooter/mac.v1.yml@yaml-templates + parameters: + AgentPoolAccessToken: ${{ parameters.agentPoolAccessToken }} diff --git a/eng/pipelines/common/ui-tests.yml b/eng/pipelines/common/ui-tests.yml new file mode 100644 index 000000000000..46bdc03972d0 --- /dev/null +++ b/eng/pipelines/common/ui-tests.yml @@ -0,0 +1,126 @@ +parameters: + androidPool: { } + iosPool: { } + windowsPool: { } + macosPool: { } + androidApiLevels: [ 30 ] + iosVersions: [ 'latest' ] + provisionatorChannel: 'latest' + agentPoolAccessToken: '' + projects: + - name: name + desc: Human Description + android: /optional/path/to/android.csproj + ios: /optional/path/to/ios.csproj + winui: /optional/path/to/winui.csproj + mac: /optional/path/to/mac.csproj + app: /optional/path/to/app.csproj + +stages: + + - stage: android_ui_tests + displayName: Android UITests + dependsOn: [] + jobs: + - ${{ each project in parameters.projects }}: + - ${{ if ne(project.android, '') }}: + - ${{ each api in parameters.androidApiLevels }}: + - ${{ if not(containsValue(project.androidApiLevelsExclude, api)) }}: + - job: android_ui_tests_${{ project.name }}_${{ api }} + timeoutInMinutes: 120 # how long to run the job before automatically cancelling + workspace: + clean: all + displayName: ${{ coalesce(project.desc, project.name) }} (API ${{ api }}) + pool: ${{ parameters.androidPool }} + variables: + ${{ if ge(api, 24) }}: + ANDROID_EMULATORS: "system-images;android-${{ api }};google_apis_playstore;x86" + ${{ if lt(api, 24) }}: + ANDROID_EMULATORS: "system-images;android-${{ api }};google_apis;x86" + REQUIRED_XCODE: $(DEVICETESTS_REQUIRED_XCODE) + steps: + - template: ui-tests-steps.yml + parameters: + platform: android + version: ${{ api }} + path: ${{ project.android }} + app: ${{ project.app }} + device: android-emulator-32_${{ api }} + provisionatorChannel: ${{ parameters.provisionatorChannel }} + agentPoolAccessToken: ${{ parameters.agentPoolAccessToken }} + + - stage: ios_ui_tests + displayName: iOS UITests + dependsOn: [] + jobs: + - ${{ each project in parameters.projects }}: + - ${{ if ne(project.ios, '') }}: + - ${{ each version in parameters.iosVersions }}: + - ${{ if not(containsValue(project.iosVersionsExclude, version)) }}: + - job: ios_ui_tests_${{ project.name }}_${{ replace(version, '.', '_') }} + workspace: + clean: all + displayName: ${{ coalesce(project.desc, project.name) }} (v${{ version }}) + pool: ${{ parameters.iosPool }} + variables: + REQUIRED_XCODE: $(DEVICETESTS_REQUIRED_XCODE) + steps: + - template: ui-tests-steps.yml + parameters: + platform: ios + ${{ if eq(version, 'latest') }}: + version: 16.2 + ${{ if ne(version, 'latest') }}: + version: ${{ version }} + path: ${{ project.ios }} + app: ${{ project.app }} + ${{ if eq(version, 'latest') }}: + device: ios-simulator-64 + ${{ if ne(version, 'latest') }}: + device: ios-simulator-64_${{ version }} + provisionatorChannel: ${{ parameters.provisionatorChannel }} + agentPoolAccessToken: ${{ parameters.agentPoolAccessToken }} + + - stage: winui_ui_tests + displayName: WinUI UITests + dependsOn: [] + jobs: + - ${{ each project in parameters.projects }}: + - ${{ if ne(project.winui, '') }}: + - job: winui_ui_tests_${{ project.name }} + workspace: + clean: all + displayName: ${{ coalesce(project.desc, project.name) }} + pool: ${{ parameters.windowsPool }} + steps: + - template: ui-tests-steps.yml + parameters: + platform: windows + version: "10.0.19041" + device: windows10 + path: ${{ project.winui }} + app: ${{ project.app }} + provisionatorChannel: ${{ parameters.provisionatorChannel }} + agentPoolAccessToken: ${{ parameters.agentPoolAccessToken }} + + - stage: mac_ui_tests + displayName: macOS UITests + dependsOn: [] + jobs: + - ${{ each project in parameters.projects }}: + - ${{ if ne(project.mac, '') }}: + - job: mac_ui_tests_${{ project.name }} + workspace: + clean: all + displayName: ${{ coalesce(project.desc, project.name) }} + pool: ${{ parameters.macosPool }} + steps: + - template: ui-tests-steps.yml + parameters: + platform: catalyst + version: "13.1" + device: mac + path: ${{ project.mac }} + app: ${{ project.app }} + provisionatorChannel: ${{ parameters.provisionatorChannel }} + agentPoolAccessToken: ${{ parameters.agentPoolAccessToken }} \ No newline at end of file diff --git a/eng/pipelines/ui-tests.yml b/eng/pipelines/ui-tests.yml new file mode 100644 index 000000000000..152785c5864c --- /dev/null +++ b/eng/pipelines/ui-tests.yml @@ -0,0 +1,150 @@ +trigger: + branches: + include: + - main + - release/* + - loc + tags: + include: + - '*' + paths: + include: + - '*' + exclude: + - .github/* + - docs/* + - src/Templates/* + - CODE-OF-CONDUCT.md + - CONTRIBUTING.md + - LICENSE.TXT + - PATENTS.TXT + - README.md + - SECURITY.md + - THIRD-PARTY-NOTICES.TXT + +pr: + branches: + include: + - main + - release/* + paths: + include: + - '*' + exclude: + - .github/* + - docs/* + - src/Templates/* + - CODE-OF-CONDUCT.md + - CONTRIBUTING.md + - LICENSE.TXT + - PATENTS.TXT + - README.md + - SECURITY.md + - THIRD-PARTY-NOTICES.TXT + +variables: + - template: /eng/pipelines/common/variables.yml + - name: AgentPoolAccessToken + value: $(botdeploy--azdo--token--register--xamarin-public--untrusted) + +parameters: + - name: provisionatorChannel + displayName: 'Provisionator channel' + type: string + default: 'latest' # Support for launching a build against a Provisionator PR (e.g., pr/[github-account-name]/[pr-number]) as a means to test in-progress Provisionator changes + + - name: BuildEverything + type: boolean + default: false + + - name: androidPool + type: object + default: + name: $(androidTestsVmPool) + vmImage: $(androidTestsVmImage) + demands: + - macOS.Name -equals Ventura + - macOS.Architecture -equals x64 + + - name: iosPool + type: object + default: + name: $(androidTestsVmPool) + vmImage: $(androidTestsVmImage) + demands: + - macOS.Name -equals Ventura + - macOS.Architecture -equals x64 + + - name: windowsPool + type: object + default: + name: $(windowsTestsVmPool) + vmImage: $(windowsTestsVmImage) + + - name: macosPool + type: object + default: + name: $(macosTestsVmPool) + vmImage: $(macosTestsVmImage) + + +resources: + repositories: + - repository: yaml-templates + type: github + name: xamarin/yaml-templates + endpoint: xamarin + ref: refs/heads/main + +stages: + + - template: common/ui-tests.yml + parameters: + androidPool: ${{ parameters.androidPool }} + iosPool: ${{ parameters.iosPool }} + windowsPool: ${{ parameters.windowsPool }} + macosPool: ${{ parameters.macosPool }} + agentPoolAccessToken: $(AgentPoolAccessToken) + ${{ if or(parameters.BuildEverything, and(ne(variables['Build.Reason'], 'PullRequest'), eq(variables['System.TeamProject'], 'devdiv'))) }}: + androidApiLevels: [ 30 ] + # androidApiLevels: [ 30, 29, 28, 27, 26, 25, 24, 23, 22, 21 ] # fix the issue of getting the test results off + iosVersions: [ 'latest' ] + provisionatorChannel: ${{ parameters.provisionatorChannel }} + ${{ if not(or(parameters.BuildEverything, and(ne(variables['Build.Reason'], 'PullRequest'), eq(variables['System.TeamProject'], 'devdiv')))) }}: + androidApiLevels: [ 30 ] + # androidApiLevels: [ 30, 21 ] # fix the issue of getting the test results off + iosVersions: [ 'latest' ] + provisionatorChannel: ${{ parameters.provisionatorChannel }} + projects: + # - name: essentials + # desc: Essentials + # androidApiLevelsExclude: [25] # Ignore for now API25 since the runs's are not stable + # android: $(System.DefaultWorkingDirectory)/src/Essentials/test/DeviceTests/Essentials.DeviceTests.csproj + # ios: $(System.DefaultWorkingDirectory)/src/Essentials/test/DeviceTests/Essentials.DeviceTests.csproj + # - name: graphics + # desc: Graphics + # androidApiLevelsExclude: [25] # Ignore for now API25 since the runs's are not stable + # android: $(System.DefaultWorkingDirectory)/src/Graphics/tests/DeviceTests/Graphics.DeviceTests.csproj + # ios: $(System.DefaultWorkingDirectory)/src/Graphics/tests/DeviceTests/Graphics.DeviceTests.csproj + # - name: core + # desc: Core + # androidApiLevelsExclude: [25] # Ignore for now API25 since the runs's are not stable + # android: $(System.DefaultWorkingDirectory)/src/Core/tests/DeviceTests/Core.DeviceTests.csproj + # iosVersionsExclude: [ '12.4'] # Ignore iOS 12.4 while we can't make it work on CI + # ios: $(System.DefaultWorkingDirectory)/src/Core/tests/DeviceTests/Core.DeviceTests.csproj + - name: controls + desc: Controls + androidApiLevelsExclude: [25] # Ignore for now API25 since the runs's are not stable + android: $(System.DefaultWorkingDirectory)/src/Controls/tests/UITests/Controls.AppiumTests.csproj + app: $(System.DefaultWorkingDirectory)/src/Controls/samples/Controls.Sample.UITests/Controls.Sample.UITests.csproj + iosVersionsExclude: [ '12.4'] # Ignore iOS 12.4 while we can't make it work on CI + ios: $(System.DefaultWorkingDirectory)/src/Controls/tests/UITests/Controls.AppiumTests.csproj + winui: $(System.DefaultWorkingDirectory)/src/Controls/tests/UITests/Controls.AppiumTests.csproj + mac: $(System.DefaultWorkingDirectory)/src/Controls/tests/UITests/Controls.AppiumTests.csproj + # - name: blazorwebview + # desc: BlazorWebView + # androidApiLevelsExclude: [ 27, 26, 25, 24, 23, 22, 21 ] # BlazorWebView requires a recent version of Chrome + # android: $(System.DefaultWorkingDirectory)/src/BlazorWebView/tests/MauiDeviceTests/MauiBlazorWebView.DeviceTests.csproj + # iosVersionsExclude: [ '12.4'] # Ignore iOS 12.4 while we can't make it work on CI + # ios: $(System.DefaultWorkingDirectory)/src/BlazorWebView/tests/MauiDeviceTests/MauiBlazorWebView.DeviceTests.csproj + diff --git a/eng/scripts/appium-install.ps1 b/eng/scripts/appium-install.ps1 new file mode 100644 index 000000000000..4c44f3c69814 --- /dev/null +++ b/eng/scripts/appium-install.ps1 @@ -0,0 +1,25 @@ +node -v +npm install -g npm +node -v +npm install -g appium@next +appium -v +$x = appium driver list --installed --json | ConvertFrom-Json +if(!$x.windows) +{ + appium driver install --source=npm appium-windows-driver +} + +if(!$x.uiautomator2) +{ + appium driver install uiautomator2 +} + +if(!$x.xcuitest) +{ + appium driver install xcuitest +} + +if(!$x.mac2) +{ + appium driver install mac2 +} \ No newline at end of file diff --git a/src/Controls/samples/Controls.Sample.Sandbox/MainPage.xaml b/src/Controls/samples/Controls.Sample.Sandbox/MainPage.xaml index d4b53136c417..e1762ab92d18 100644 --- a/src/Controls/samples/Controls.Sample.Sandbox/MainPage.xaml +++ b/src/Controls/samples/Controls.Sample.Sandbox/MainPage.xaml @@ -3,5 +3,4 @@ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Maui.Controls.Sample.MainPage" xmlns:local="clr-namespace:Maui.Controls.Sample"> - \ No newline at end of file diff --git a/src/Controls/samples/Controls.Sample.Sandbox/Properties/launchSettings.json b/src/Controls/samples/Controls.Sample.Sandbox/Properties/launchSettings.json index edf8aadcc83b..3b7edaf2a58f 100644 --- a/src/Controls/samples/Controls.Sample.Sandbox/Properties/launchSettings.json +++ b/src/Controls/samples/Controls.Sample.Sandbox/Properties/launchSettings.json @@ -1,8 +1,8 @@ { "profiles": { "Windows Machine": { - "commandName": "MsixPackage", - "nativeDebugging": false + "commandName": "MsixPackage", + "nativeDebugging": false } } } \ No newline at end of file diff --git a/src/Controls/samples/Controls.Sample.UITests/Controls.Sample.UITests.csproj b/src/Controls/samples/Controls.Sample.UITests/Controls.Sample.UITests.csproj new file mode 100644 index 000000000000..ed05e6d3c251 --- /dev/null +++ b/src/Controls/samples/Controls.Sample.UITests/Controls.Sample.UITests.csproj @@ -0,0 +1,49 @@ + + + + $(MauiPlatforms) + Exe + true + false + + maccatalyst-x64 + + + + Controls UITests + com.microsoft.maui.uitests + 1.0 + 1 + <_FastDeploymentDiagnosticLogging>True + None + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Controls/samples/Controls.Sample.UITests/MainPage.xaml b/src/Controls/samples/Controls.Sample.UITests/MainPage.xaml new file mode 100644 index 000000000000..828aa9a50b4b --- /dev/null +++ b/src/Controls/samples/Controls.Sample.UITests/MainPage.xaml @@ -0,0 +1,18 @@ + + + +