This commit is contained in:
Jerome Laban 2019-09-07 19:57:08 -04:00
Родитель 15efcff14e
Коммит cfcc68f1d2
25 изменённых файлов: 295 добавлений и 121 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -235,3 +235,4 @@ Resource.Designer.cs
/build/*.nupkg /build/*.nupkg
src/nuget_override.props src/nuget_override.props
.DS_Store

Просмотреть файл

@ -138,3 +138,42 @@ jobs:
PathtoPublish: $(build.artifactstagingdirectory) PathtoPublish: $(build.artifactstagingdirectory)
ArtifactName: uno-uitest-tests ArtifactName: uno-uitest-tests
ArtifactType: Container ArtifactType: Container
- job: iOS_Tests
variables:
CI_Build: true
SourceLinkEnabled: false
pool:
vmImage: 'macOS-10.14'
steps:
- checkout: self
clean: true
- bash: /bin/bash -c "sudo $AGENT_HOMEDIRECTORY/scripts/select-xamarin-sdk.sh 5_18_1"
displayName: Select Xamarin Version
- bash: |
chmod +x $(build.sourcesdirectory)/build/build-ios.sh
$(build.sourcesdirectory)/build/build-ios.sh
displayName: Build and Test
env:
BUILD_SOURCESDIRECTORY: "$(build.sourcesdirectory)"
BUILD_ARTIFACTSTAGINGDIRECTORY: "$(build.artifactstagingdirectory)"
- task: PublishTestResults@2
condition: always()
inputs:
testRunTitle: 'iOS Test Run'
testResultsFormat: 'NUnit'
testResultsFiles: '$(build.sourcesdirectory)/build/TestResult.xml'
- task: PublishBuildArtifacts@1
condition: always()
inputs:
PathtoPublish: $(build.artifactstagingdirectory)
ArtifactName: uno-uitest-tests
ArtifactType: Container

23
build/build-ios.sh Normal file
Просмотреть файл

@ -0,0 +1,23 @@
#!/bin/bash
echo "Lising iOS simulators"
xcrun simctl list devices --json
/Applications/Xcode.app/Contents/Developer/Applications/Simulator.app/Contents/MacOS/Simulator &
cd $BUILD_SOURCESDIRECTORY
msbuild /r /p:Configuration=Release $BUILD_SOURCESDIRECTORY/src/Sample/Sample.UITests/Sample.UITests.csproj
msbuild /r /p:Configuration=Release "/p:Platform=iPhoneSimulator" $BUILD_SOURCESDIRECTORY/src/Sample/Sample.iOS/Sample.iOS.csproj
cd $BUILD_SOURCESDIRECTORY/build
mono nuget.exe install NUnit.ConsoleRunner -Version 3.10.0
export UNO_UITEST_PLATFORM=iOS
export UNO_UITEST_IOSBUNDLE_PATH=$BUILD_SOURCESDIRECTORY/src/Sample/Sample.iOS/bin/iPhoneSimulator/Release/Sample.app
export UNO_UITEST_SCREENSHOT_PATH=$BUILD_ARTIFACTSTAGINGDIRECTORY/screenshots/ios
mkdir -p $UNO_UITEST_SCREENSHOT_PATH
mono $BUILD_SOURCESDIRECTORY/build/NUnit.ConsoleRunner.3.10.0/tools/nunit3-console.exe --inprocess --agents=1 --workers=1 $BUILD_SOURCESDIRECTORY/src/Sample/Sample.UITests/bin/Release/net47/Sample.UITests.dll > $BUILD_ARTIFACTSTAGINGDIRECTORY/screenshots/ios/nunit-log.txt 2>&1

Просмотреть файл

@ -16,10 +16,11 @@ export UNO_UITEST_DRIVERPATH_CHROME=$BUILD_SOURCESDIRECTORY/build/node_modules/c
export UNO_UITEST_CHROME_BINARY_PATH=$BUILD_SOURCESDIRECTORY/build/node_modules/puppeteer/.local-chromium/linux-637110/chrome-linux/chrome export UNO_UITEST_CHROME_BINARY_PATH=$BUILD_SOURCESDIRECTORY/build/node_modules/puppeteer/.local-chromium/linux-637110/chrome-linux/chrome
export UNO_UITEST_SCREENSHOT_PATH=$BUILD_ARTIFACTSTAGINGDIRECTORY/screenshots/wasm export UNO_UITEST_SCREENSHOT_PATH=$BUILD_ARTIFACTSTAGINGDIRECTORY/screenshots/wasm
export UNO_UITEST_PLATFORM=Browser export UNO_UITEST_PLATFORM=Browser
export UNO_UITEST_CHROME_CONTAINER_MODE=true
mkdir -p $UNO_UITEST_SCREENSHOT_PATH mkdir -p $UNO_UITEST_SCREENSHOT_PATH
## The python server serves the current working directory, and may be changed by the nunit runner ## The python server serves the current working directory, and may be changed by the nunit runner
bash -c "cd $BUILD_SOURCESDIRECTORY/src/Sample/Sample.Wasm/bin/Release/netstandard2.0/dist/; python server.py &" bash -c "cd $BUILD_SOURCESDIRECTORY/src/Sample/Sample.Wasm/bin/Release/netstandard2.0/dist/; python server.py &"
mono $BUILD_SOURCESDIRECTORY/build/NUnit.ConsoleRunner.3.10.0/tools/nunit3-console.exe $BUILD_SOURCESDIRECTORY/src/Sample/Sample.UITests/bin/Release/net47/Sample.UITests.dll mono $BUILD_SOURCESDIRECTORY/build/NUnit.ConsoleRunner.3.10.0/tools/nunit3-console.exe --trace=Verbose --inprocess --agents=1 --workers=1 $BUILD_SOURCESDIRECTORY/src/Sample/Sample.UITests/bin/Release/net47/Sample.UITests.dll

Просмотреть файл

@ -15,7 +15,6 @@
<AndroidApplication>true</AndroidApplication> <AndroidApplication>true</AndroidApplication>
<AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile> <AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies> <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<AndroidUseLatestPlatformSdk>False</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v9.0</TargetFrameworkVersion> <TargetFrameworkVersion>v9.0</TargetFrameworkVersion>
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest> <AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
<AndroidUseIntermediateDesignerFile>True</AndroidUseIntermediateDesignerFile> <AndroidUseIntermediateDesignerFile>True</AndroidUseIntermediateDesignerFile>
@ -34,10 +33,6 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<AndroidUseSharedRuntime>True</AndroidUseSharedRuntime> <AndroidUseSharedRuntime>True</AndroidUseSharedRuntime>
<AndroidLinkMode>None</AndroidLinkMode> <AndroidLinkMode>None</AndroidLinkMode>
<AotAssemblies>false</AotAssemblies>
<EnableLLVM>false</EnableLLVM>
<AndroidEnableProfiledAot>false</AndroidEnableProfiledAot>
<BundleAssemblies>false</BundleAssemblies>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>portable</DebugType> <DebugType>portable</DebugType>
@ -52,11 +47,7 @@
<AndroidLinkMode>SdkOnly</AndroidLinkMode> <AndroidLinkMode>SdkOnly</AndroidLinkMode>
<AndroidCreatePackagePerAbi>true</AndroidCreatePackagePerAbi> <AndroidCreatePackagePerAbi>true</AndroidCreatePackagePerAbi>
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk> <EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
<AotAssemblies>false</AotAssemblies>
<EnableLLVM>false</EnableLLVM>
<AndroidEnableSGenConcurrent>true</AndroidEnableSGenConcurrent> <AndroidEnableSGenConcurrent>true</AndroidEnableSGenConcurrent>
<AndroidEnableProfiledAot>false</AndroidEnableProfiledAot>
<BundleAssemblies>false</BundleAssemblies>
<AndroidSupportedAbis>armeabi-v7a;x86;arm64-v8a</AndroidSupportedAbis> <AndroidSupportedAbis>armeabi-v7a;x86;arm64-v8a</AndroidSupportedAbis>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

Просмотреть файл

@ -39,6 +39,12 @@ namespace Sample
/// <param name="e">Details about the launch request and process.</param> /// <param name="e">Details about the launch request and process.</param>
protected override void OnLaunched(LaunchActivatedEventArgs e) protected override void OnLaunched(LaunchActivatedEventArgs e)
{ {
#if __IOS__
// requires Xamarin Test Cloud Agent
Xamarin.Calabash.Start();
#endif
#if DEBUG #if DEBUG
if(System.Diagnostics.Debugger.IsAttached) if(System.Diagnostics.Debugger.IsAttached)
{ {

Просмотреть файл

@ -13,12 +13,12 @@
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<ScrollViewer Grid.Column="0"> <ScrollViewer Grid.Column="0">
<ItemsControl ItemsSource="{x:Bind TestControls}"> <ItemsControl>
<ItemsControl.ItemTemplate> <HyperlinkButton x:Uid="ComboBox01" Content="ComboBox 1" Click="HyperlinkButton_Click" Tag="Sample.Shared.Tests.ComboBox_Tests" />
<DataTemplate> <HyperlinkButton x:Uid="CheckBox01" Content="CheckBox 1" Click="HyperlinkButton_Click" Tag="Sample.Shared.Tests.CheckBox_Tests" />
<HyperlinkButton Content="{Binding Name}" Click="HyperlinkButton_Click" /> <HyperlinkButton x:Uid="RadioButton01" Content="RadioButton 01" Click="HyperlinkButton_Click" Tag="Sample.Shared.Tests.RadioButton_Tests_01" />
</DataTemplate> <HyperlinkButton x:Uid="TextBox01" Content="TextBox 01" Click="HyperlinkButton_Click" Tag="Sample.Shared.Tests.TextBox_Tests_01" />
</ItemsControl.ItemTemplate> <HyperlinkButton x:Uid="DragCoordinates01" Content="DragCoordinates 01" Click="HyperlinkButton_Click" Tag="Sample.Shared.Tests.DragCoordinates_Tests" />
</ItemsControl> </ItemsControl>
</ScrollViewer> </ScrollViewer>
<Border Grid.Column="1" Margin="12"> <Border Grid.Column="1" Margin="12">

Просмотреть файл

@ -26,21 +26,13 @@ namespace Sample
public MainPage() public MainPage()
{ {
this.InitializeComponent(); this.InitializeComponent();
TestControls.Add(new TestControl("ComboBox 1", "Sample.Shared.Tests.ComboBox_Tests"));
TestControls.Add(new TestControl("CheckBox 1", "Sample.Shared.Tests.CheckBox_Tests"));
TestControls.Add(new TestControl("RadioButton 01", "Sample.Shared.Tests.RadioButton_Tests_01"));
TestControls.Add(new TestControl("TextBox 01", "Sample.Shared.Tests.TextBox_Tests_01"));
TestControls.Add(new TestControl("DragCoordinates 01", "Sample.Shared.Tests.DragCoordinates_Tests"));
} }
public ObservableCollection<TestControl> TestControls { get; } = new ObservableCollection<TestControl>();
private void HyperlinkButton_Click(object sender, RoutedEventArgs e) private void HyperlinkButton_Click(object sender, RoutedEventArgs e)
{ {
if(sender is HyperlinkButton button && button.DataContext is TestControl tc) if(sender is HyperlinkButton button && button.Tag is string typeName)
{ {
var type = Type.GetType(tc.Type); var type = Type.GetType(typeName);
var instance = Activator.CreateInstance(type) as FrameworkElement; var instance = Activator.CreateInstance(type) as FrameworkElement;
@ -51,17 +43,4 @@ namespace Sample
} }
} }
} }
[Bindable]
public class TestControl
{
public TestControl(string name, string type)
{
Name = name;
Type = type;
}
public string Name { get; }
public string Type { get; }
}
} }

Просмотреть файл

@ -1,6 +1,9 @@
using System; using System;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NUnit.Framework; using NUnit.Framework;
using Sample.UITests; using Sample.UITests;
using Uno.UITest; using Uno.UITest;
@ -13,12 +16,23 @@ namespace SamplesApp.UITests
{ {
public const string UITestPlatform = "UNO_UITEST_PLATFORM"; public const string UITestPlatform = "UNO_UITEST_PLATFORM";
public const string UITEST_IOSBUNDLE_PATH = "UNO_UITEST_IOSBUNDLE_PATH"; public const string UITEST_IOSBUNDLE_PATH = "UNO_UITEST_IOSBUNDLE_PATH";
public const string UITEST_IOSDEVICE_ID = "UITEST_IOSDEVICE_ID";
public const string UITEST_ANDROIDAPK_PATH = "UNO_UITEST_ANDROIDAPK_PATH"; public const string UITEST_ANDROIDAPK_PATH = "UNO_UITEST_ANDROIDAPK_PATH";
public const string UITEST_SCREENSHOT_PATH = "UNO_UITEST_SCREENSHOT_PATH"; public const string UITEST_SCREENSHOT_PATH = "UNO_UITEST_SCREENSHOT_PATH";
private const string DriverPath = @"..\..\..\..\..\..\build\node_modules\chromedriver\lib\chromedriver"; private const string DriverPath = @"..\..\..\..\..\..\build\node_modules\chromedriver\lib\chromedriver";
private static IApp _currentApp;
public static IApp StartApp(bool alreadyRunningApp) public static IApp ColdStartApp()
=> Xamarin.UITest.TestEnvironment.Platform == Xamarin.UITest.TestPlatform.Local
? StartApp(alreadyRunningApp: false)
: null;
public static IApp AttachToApp()
// If the retry count is set, the test already failed. Retry the test with restarting the app.
=> StartApp(alreadyRunningApp: TestContext.CurrentContext.CurrentRepeatCount == 0);
private static IApp StartApp(bool alreadyRunningApp)
{ {
Console.WriteLine($"Starting app ({alreadyRunningApp})"); Console.WriteLine($"Starting app ({alreadyRunningApp})");
@ -47,7 +61,15 @@ namespace SamplesApp.UITests
return CreateiOSApp(alreadyRunningApp); return CreateiOSApp(alreadyRunningApp);
case Platform.Browser: case Platform.Browser:
return CreateBrowserApp(); if(alreadyRunningApp)
{
return CreateBrowserApp(alreadyRunningApp);
}
else
{
// Skip cold app start, there's no notion of reuse active browser yet.
return null;
}
default: default:
throw new Exception($"Platform {localPlatform} is not enabled."); throw new Exception($"Platform {localPlatform} is not enabled.");
@ -55,22 +77,52 @@ namespace SamplesApp.UITests
} }
} }
private static IApp CreateBrowserApp() => Uno.UITest.Selenium.ConfigureApp private static IApp CreateBrowserApp(bool alreadyRunningApp)
{
if(_currentApp != null)
{
if(!alreadyRunningApp)
{
_currentApp.Dispose();
}
else
{
return _currentApp;
}
}
try
{
var app = _currentApp = Uno.UITest.Selenium.ConfigureApp
.WebAssembly .WebAssembly
.Uri(new Uri(Constants.DefaultUri)) .Uri(new Uri(Constants.DefaultUri))
.ChromeDriverLocation(Path.Combine(TestContext.CurrentContext.TestDirectory, DriverPath.Replace('\\', Path.DirectorySeparatorChar))) .ChromeDriverLocation(Path.Combine(TestContext.CurrentContext.TestDirectory,
DriverPath.Replace('\\', Path.DirectorySeparatorChar)))
.ScreenShotsPath(TestContext.CurrentContext.TestDirectory) .ScreenShotsPath(TestContext.CurrentContext.TestDirectory)
#if DEBUG #if DEBUG
.Headless(false) .Headless(false)
.SeleniumArgument("--remote-debugging-port=9222")
#endif #endif
.StartApp(); .StartApp();
return app;
}
catch(Exception ex)
{
Console.Error.WriteLine(ex.Message);
throw;
}
}
private static IApp CreateAndroidApp(bool alreadyRunningApp) private static IApp CreateAndroidApp(bool alreadyRunningApp)
{
if(string.IsNullOrEmpty(Environment.GetEnvironmentVariable("ANDROID_HOME")))
{ {
// To set in case of Xamarin.UITest errors // To set in case of Xamarin.UITest errors
// //
// Environment.SetEnvironmentVariable("ANDROID_HOME", @"C:\Program Files (x86)\Android\android-sdk"); Environment.SetEnvironmentVariable("ANDROID_HOME", @"C:\Program Files (x86)\Android\android-sdk");
// Environment.SetEnvironmentVariable("JAVA_HOME", @"C:\Program Files\Android\Jdk\microsoft_dist_openjdk_1.8.0.25"); Environment.SetEnvironmentVariable("JAVA_HOME", @"C:\Program Files\Android\Jdk\microsoft_dist_openjdk_1.8.0.25");
}
var androidConfig = Xamarin.UITest.ConfigureApp var androidConfig = Xamarin.UITest.ConfigureApp
.Android .Android
@ -90,49 +142,76 @@ namespace SamplesApp.UITests
? androidConfig.ConnectToApp() ? androidConfig.ConnectToApp()
: androidConfig.StartApp(); : androidConfig.StartApp();
ApplyScreenShotPath();
return app.ToUnoApp(); return app.ToUnoApp();
} }
private static void ApplyScreenShotPath()
{
var value = Environment.GetEnvironmentVariable(UITEST_SCREENSHOT_PATH);
if(!string.IsNullOrWhiteSpace(value))
{
Environment.CurrentDirectory = value;
}
else
{
Environment.CurrentDirectory = Path.GetDirectoryName(new Uri(typeof(AppInitializer).Assembly.Location).LocalPath);
}
}
private static IApp CreateiOSApp(bool alreadyRunningApp) private static IApp CreateiOSApp(bool alreadyRunningApp)
{ {
var iOSConfig = Xamarin.UITest.ConfigureApp var iOSConfig = Xamarin.UITest.ConfigureApp
.iOS .iOS
.Debug() .Debug()
.DeviceIdentifier(GetiOSDeviceId())
.LogDirectory(Environment.GetEnvironmentVariable(UITEST_SCREENSHOT_PATH))
.EnableLocalScreenshots(); .EnableLocalScreenshots();
if(GetiOSAppBundlePath() is string bundlePath) if(GetiOSAppBundlePath() is string bundlePath)
{ {
Console.WriteLine($"Using AppBundle Path: {bundlePath}");
iOSConfig = iOSConfig.AppBundle(bundlePath); iOSConfig = iOSConfig.AppBundle(bundlePath);
} }
else else
{ {
iOSConfig = iOSConfig.InstalledApp(Constants.AndroidAppName); Console.WriteLine($"Using Installed App: {Constants.iOSAppName}");
iOSConfig = iOSConfig.InstalledApp(Constants.iOSAppName);
} }
var app = alreadyRunningApp var app = alreadyRunningApp
? iOSConfig.ConnectToApp() ? iOSConfig.ConnectToApp()
: iOSConfig.StartApp(); : iOSConfig.StartApp(Xamarin.UITest.Configuration.AppDataMode.DoNotClear);
ApplyScreenShotPath();
return app.ToUnoApp(); return app.ToUnoApp();
} }
private static string GetiOSDeviceId()
{
var environmentDeviceId = Environment.GetEnvironmentVariable(UITEST_IOSDEVICE_ID) ?? "";
if(!Guid.TryParse(environmentDeviceId, out var deviceId))
{
var deviceName = !string.IsNullOrEmpty(environmentDeviceId) ? environmentDeviceId : Constants.iOSDeviceNameOrId;
Process process = new Process();
process.StartInfo.FileName = "xcrun";
process.StartInfo.Arguments = $"simctl list devices -j \"{deviceName}\" available";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.Start();
var deviceList = JsonConvert.DeserializeObject(process.StandardOutput.ReadToEnd()) as JObject;
if(deviceList != null
&& deviceList["devices"] is JObject systems)
{
foreach(var system in systems.Values())
{
if(system is JArray devices)
{
foreach(var device in devices)
{
if(device is JObject dev)
{
return device["udid"].ToString();
}
}
}
}
}
process.WaitForExit();
}
return environmentDeviceId;
}
private static string GetAndroidApkPath() private static string GetAndroidApkPath()
{ {
var value = Environment.GetEnvironmentVariable(UITEST_ANDROIDAPK_PATH); var value = Environment.GetEnvironmentVariable(UITEST_ANDROIDAPK_PATH);

Просмотреть файл

@ -14,7 +14,7 @@ namespace Sample.UITests
[Test] [Test]
public void CheckBox01() public void CheckBox01()
{ {
Query checkBoxSelector = q => q.Text("CheckBox 1"); Query checkBoxSelector = q => q.Marked("CheckBox01");
App.WaitForElement(checkBoxSelector); App.WaitForElement(checkBoxSelector);
App.Tap(checkBoxSelector); App.Tap(checkBoxSelector);

Просмотреть файл

@ -11,8 +11,9 @@ namespace Sample.UITests
{ {
public const string DefaultUri = "http://localhost:51669/"; public const string DefaultUri = "http://localhost:51669/";
public const string ChromeDriver = @"C:\s\ChromeDriver\74.0.3729.6"; public const string ChromeDriver = @"C:\s\ChromeDriver\74.0.3729.6";
public readonly static string iOSAppName; public readonly static string iOSAppName = "uno.platform.uitestsample";
public readonly static string AndroidAppName = "uno.platform.uitestsample"; public readonly static string AndroidAppName = "uno.platform.uitestsample";
public readonly static string iOSDeviceNameOrId = "iPad Pro (12.9-inch) (3rd generation)";
public readonly static Platform CurrentPlatform = Platform.Browser; public readonly static Platform CurrentPlatform = Platform.Browser;
} }

Просмотреть файл

@ -15,7 +15,7 @@ namespace Sample.UITests
[Test] [Test]
public void DragBorder01() public void DragBorder01()
{ {
Query testSelector = q => q.Text("DragCoordinates 01"); Query testSelector = q => q.Marked("DragCoordinates01");
Query rootCanvas = q => q.Marked("rootCanvas"); Query rootCanvas = q => q.Marked("rootCanvas");
Query myBorder = q => q.Marked("myBorder"); Query myBorder = q => q.Marked("myBorder");
@ -43,12 +43,17 @@ namespace Sample.UITests
App.Screenshot("DragBorder01 - Step 2"); App.Screenshot("DragBorder01 - Step 2");
if(Xamarin.UITest.TestEnvironment.Platform == Xamarin.UITest.TestPlatform.TestCloudAndroid if(Xamarin.UITest.TestEnvironment.Platform == Xamarin.UITest.TestPlatform.TestCloudAndroid
|| SamplesApp.UITests.AppInitializer.GetLocalPlatform() == Platform.Android) || SamplesApp.UITests.AppInitializer.GetLocalPlatform() == Platform.Android
|| Xamarin.UITest.TestEnvironment.Platform == Xamarin.UITest.TestPlatform.TestCloudiOS
|| SamplesApp.UITests.AppInitializer.GetLocalPlatform() == Platform.iOS)
{ {
// PointerEvents don't fire properly on Android, causing this test to fail https://github.com/unoplatform/uno/issues/1257 // PointerEvents don't fire properly on Android, causing this test to fail https://github.com/unoplatform/uno/issues/1257
// PointerEvents are reporting an off by one value. May be fixed by https://github.com/unoplatform/uno/issues/1256
return; return;
} }
var value = App.Query(q => topValue(q).GetDependencyPropertyValue("Text").Value<string>()).First();
App.WaitForDependencyPropertyValue(topValue, "Text", "50"); App.WaitForDependencyPropertyValue(topValue, "Text", "50");
App.WaitForDependencyPropertyValue(leftValue, "Text", "50"); App.WaitForDependencyPropertyValue(leftValue, "Text", "50");

Просмотреть файл

@ -14,7 +14,7 @@ namespace Sample.UITests
[Test] [Test]
public void RadioButton01() public void RadioButton01()
{ {
Query testSelector = q => q.Text("RadioButton 01"); Query testSelector = q => q.Marked("RadioButton01");
App.WaitForElement(testSelector); App.WaitForElement(testSelector);
App.Tap(testSelector); App.Tap(testSelector);

Просмотреть файл

@ -7,8 +7,9 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.1.1" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.1.1" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<PackageReference Include="NUnit" Version="3.12.0" /> <PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.12.0" /> <PackageReference Include="NUnit3TestAdapter" Version="3.15.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

Просмотреть файл

@ -8,26 +8,34 @@ namespace Sample.UITests
{ {
public class TestBase public class TestBase
{ {
private IApp _app;
static TestBase() static TestBase()
{ {
// Start the app only once, so the tests runs don't restart it // Start the app only once, so the tests runs don't restart it
// and gain some time for the tests. // and gain some time for the tests.
AppInitializer.StartApp(alreadyRunningApp: false); AppInitializer.ColdStartApp();
} }
protected IApp App { get; private set; } protected IApp App
{
get => _app;
private set
{
_app = value;
Uno.UITest.Helpers.Queries.Helpers.App = value;
}
}
[SetUp] [SetUp]
public void StartApp() public void StartApp()
{ {
App = AppInitializer.StartApp(alreadyRunningApp: true); App = AppInitializer.AttachToApp();
Uno.UITest.Helpers.Queries.Helpers.App = App;
} }
[TearDown] [TearDown]
public void CloseApp() public void CloseApp()
{ {
App.Dispose();
} }
} }
} }

Просмотреть файл

@ -15,7 +15,7 @@ namespace Sample.UITests
[Test] [Test]
public void TextBox01() public void TextBox01()
{ {
Query testSelector = q => q.Text("TextBox 01"); Query testSelector = q => q.Marked("TextBox01");
Query tb01 = q => q.Marked("tb01"); Query tb01 = q => q.Marked("tb01");
StringQuery textSelector = q => StringQuery textSelector = q =>
tb01(q).GetDependencyPropertyValue("Text").Value<string>(); tb01(q).GetDependencyPropertyValue("Text").Value<string>();

Просмотреть файл

@ -1,11 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>UnoQuickStart.iOS</string> <string>UnoQuickStart.iOS</string>
<key>CFBundleIdentifier</key>
<string>com.companyname.Sample</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.0</string> <string>1.0</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
@ -13,7 +11,7 @@
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>MinimumOSVersion</key> <key>MinimumOSVersion</key>
<string></string> <string>11.0</string>
<key>UIDeviceFamily</key> <key>UIDeviceFamily</key>
<array> <array>
<integer>1</integer> <integer>1</integer>
@ -51,5 +49,9 @@
<string>Portait</string> <string>Portait</string>
<key>UILaunchImageSize</key> <key>UILaunchImageSize</key>
<string>{320, 568}</string> <string>{320, 568}</string>
<key>CFBundleIdentifier</key>
<string>uno.platform.uitestsample</string>
<key>CFBundleName</key>
<string>Uno.UI Test Samples</string>
</dict> </dict>
</plist> </plist>

Просмотреть файл

@ -13,6 +13,9 @@
</NuGetPackageImportStamp> </NuGetPackageImportStamp>
<ResourcesDirectory>..\Sample.Shared\Strings</ResourcesDirectory> <ResourcesDirectory>..\Sample.Shared\Strings</ResourcesDirectory>
</PropertyGroup> </PropertyGroup>
<PropertyGroup>
<IsUiAutomationMappingEnabled>true</IsUiAutomationMappingEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<DebugType>portable</DebugType> <DebugType>portable</DebugType>
@ -116,6 +119,9 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Uno.UI" Version="1.46.0-dev.1991" /> <PackageReference Include="Uno.UI" Version="1.46.0-dev.1991" />
<PackageReference Include="Xamarin.TestCloud.Agent">
<Version>0.21.8</Version>
</PackageReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ImageAsset Include="Media.xcassets\AppIcons.appiconset\Contents.json"> <ImageAsset Include="Media.xcassets\AppIcons.appiconset\Contents.json">

Просмотреть файл

@ -24,7 +24,6 @@ namespace Uno.UITest.Selenium
public SeleniumApp(ChromeAppConfigurator config) public SeleniumApp(ChromeAppConfigurator config)
{ {
// --whitelisted-ips
var targetUri = GetEnvironmentVariable("UNO_UITEST_TARGETURI", config.SiteUri.OriginalString); var targetUri = GetEnvironmentVariable("UNO_UITEST_TARGETURI", config.SiteUri.OriginalString);
var driverPath = GetEnvironmentVariable("UNO_UITEST_DRIVERPATH_CHROME", config.ChromeDriverPath); var driverPath = GetEnvironmentVariable("UNO_UITEST_DRIVERPATH_CHROME", config.ChromeDriverPath);
var screenShotPath = GetEnvironmentVariable("UNO_UITEST_SCREENSHOT_PATH", config.InternalScreenShotsPath); var screenShotPath = GetEnvironmentVariable("UNO_UITEST_SCREENSHOT_PATH", config.InternalScreenShotsPath);
@ -52,7 +51,7 @@ namespace Uno.UITest.Selenium
// //
// When InternalDetectDockerEnvironment is set, tell the daemon to listen on // When InternalDetectDockerEnvironment is set, tell the daemon to listen on
// all available interfaces // all available interfaces
Console.WriteLine($"Detected docker environment, adding whitelisted-ips"); Console.WriteLine($"Container mode enabled, adding whitelisted-ips");
options.AddArguments("--whitelisted-ips"); options.AddArguments("--whitelisted-ips");
} }
} }
@ -86,6 +85,20 @@ namespace Uno.UITest.Selenium
return hasValue ? value : defaultValue; return hasValue ? value : defaultValue;
} }
private bool GetEnvironmentVariable(string variableName, bool defaultValue)
{
var value = Environment.GetEnvironmentVariable(variableName);
var hasValue = bool.TryParse(value, out var varValue);
if(hasValue)
{
Console.WriteLine($"Overriding value with {variableName} = {value}");
}
return hasValue ? varValue : defaultValue;
}
void PerformActions(Action<Actions> action) void PerformActions(Action<Actions> action)
{ {
var actions = new OpenQA.Selenium.Interactions.Actions(_driver); var actions = new OpenQA.Selenium.Interactions.Actions(_driver);

Просмотреть файл

@ -7,10 +7,26 @@ namespace Uno.UITest.Xamarin.Extensions
{ {
public static class AppTypedSelectorExtensions public static class AppTypedSelectorExtensions
{ {
public static IAppTypedSelector<T> AsGenericAppTypedSelector<T>(this AppTypedSelector<T> selector) public static IAppTypedSelector<T> AsGenericAppTypedSelector<T>(this AppTypedSelector<object> selector)
=> new XamarinAppTypedSelector<T>(selector); => new XamarinAppTypedSelector<T>(selector);
public static AppTypedSelector<T> ToXamarinAppTypedSelector<T>(this IAppTypedSelector<T> selector) public static IAppTypedSelector<string> AsGenericAppTypedSelector(this AppTypedSelector<string> selector)
=> selector is XamarinAppTypedSelector<T> ts ? ts.Source : throw new InvalidOperationException(); => new XamarinAppTypedSelector<string>(selector.Value<object>());
public static AppTypedSelector<object> ToXamarinAppTypedSelector<T>(this IAppTypedSelector<T> selector)
{
if(selector is XamarinAppTypedSelector<T> tso)
{
return tso.Source;
}
else if(selector is XamarinAppTypedSelector<string> tss)
{
return tss.Source;
}
else
{
throw new InvalidOperationException();
}
}
} }
} }

Просмотреть файл

@ -20,7 +20,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Xamarin.UITest" Version="3.0.0" /> <PackageReference Include="Xamarin.UITest" Version="3.0.4-dev1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

Просмотреть файл

@ -1,4 +1,5 @@
using System; using System;
using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -164,7 +165,9 @@ namespace Uno.UITest.Xamarin
public T[] Query<T>(Func<IAppQuery, IAppTypedSelector<T>> query) public T[] Query<T>(Func<IAppQuery, IAppTypedSelector<T>> query)
=> _source.Query( => _source.Query(
q => query(q.AsGenericAppQuery()).ToXamarinAppTypedSelector() q => query(q.AsGenericAppQuery()).ToXamarinAppTypedSelector()
); )
.Select(o => (T)Convert.ChangeType(o, typeof(T), CultureInfo.InvariantCulture))
.ToArray();
public void Repl() public void Repl()
=> _source.Repl(); => _source.Repl();

Просмотреть файл

@ -47,22 +47,22 @@ namespace Uno.UITest.Xamarin.Extensions
=> SourceQuery.Index(index).AsGenericAppQuery(); => SourceQuery.Index(index).AsGenericAppQuery();
IAppTypedSelector<object> IAppQuery.Invoke(string methodName) IAppTypedSelector<object> IAppQuery.Invoke(string methodName)
=> SourceQuery.Invoke(methodName).AsGenericAppTypedSelector(); => SourceQuery.Invoke(methodName).AsGenericAppTypedSelector<object>();
IAppTypedSelector<object> IAppQuery.Invoke(string methodName, object arg1) IAppTypedSelector<object> IAppQuery.Invoke(string methodName, object arg1)
=> SourceQuery.Invoke(methodName, arg1).AsGenericAppTypedSelector(); => SourceQuery.Invoke(methodName, arg1).AsGenericAppTypedSelector<object>();
IAppTypedSelector<object> IAppQuery.Invoke(string methodName, object arg1, object arg2) IAppTypedSelector<object> IAppQuery.Invoke(string methodName, object arg1, object arg2)
=> SourceQuery.Invoke(methodName, arg1, arg2).AsGenericAppTypedSelector(); => SourceQuery.Invoke(methodName, arg1, arg2).AsGenericAppTypedSelector<object>();
IAppTypedSelector<object> IAppQuery.Invoke(string methodName, object arg1, object arg2, object arg3) IAppTypedSelector<object> IAppQuery.Invoke(string methodName, object arg1, object arg2, object arg3)
=> SourceQuery.Invoke(methodName, arg1, arg2, arg3).AsGenericAppTypedSelector(); => SourceQuery.Invoke(methodName, arg1, arg2, arg3).AsGenericAppTypedSelector<object>();
IAppTypedSelector<object> IAppQuery.Invoke(string methodName, object arg1, object arg2, object arg3, object arg4) IAppTypedSelector<object> IAppQuery.Invoke(string methodName, object arg1, object arg2, object arg3, object arg4)
=> SourceQuery.Invoke(methodName, arg1, arg2, arg3, arg4).AsGenericAppTypedSelector(); => SourceQuery.Invoke(methodName, arg1, arg2, arg3, arg4).AsGenericAppTypedSelector<object>();
IAppTypedSelector<object> IAppQuery.Invoke(string methodName, object arg1, object arg2, object arg3, object arg4, object arg5) IAppTypedSelector<object> IAppQuery.Invoke(string methodName, object arg1, object arg2, object arg3, object arg4, object arg5)
=> SourceQuery.Invoke(methodName, arg1, arg2, arg3, arg4, arg5).AsGenericAppTypedSelector(); => SourceQuery.Invoke(methodName, arg1, arg2, arg3, arg4, arg5).AsGenericAppTypedSelector<object>();
IInvokeJSAppQuery IAppQuery.InvokeJS(string javascript) IInvokeJSAppQuery IAppQuery.InvokeJS(string javascript)
=> SourceQuery.InvokeJS(javascript).AsGenericInvokeJSAppQuery(); => SourceQuery.InvokeJS(javascript).AsGenericInvokeJSAppQuery();

Просмотреть файл

@ -4,12 +4,12 @@ namespace Uno.UITest.Xamarin
{ {
internal class XamarinAppTypedSelector<T> : IAppTypedSelector<T> internal class XamarinAppTypedSelector<T> : IAppTypedSelector<T>
{ {
private AppTypedSelector<T> _source; private AppTypedSelector<object> _source;
public XamarinAppTypedSelector(AppTypedSelector<T> selector) public XamarinAppTypedSelector(AppTypedSelector<object> selector)
=> _source = selector; => _source = selector;
public AppTypedSelector<T> Source => _source; public AppTypedSelector<object> Source => _source;
IAppTypedSelector<object> IAppTypedSelector<T>.Invoke(string methodName) IAppTypedSelector<object> IAppTypedSelector<T>.Invoke(string methodName)
=> new XamarinAppTypedSelector<object>(_source.Invoke(methodName)); => new XamarinAppTypedSelector<object>(_source.Invoke(methodName));
@ -30,6 +30,6 @@ namespace Uno.UITest.Xamarin
=> new XamarinAppTypedSelector<object>(_source.Invoke(methodName, arg1, arg2, arg3, arg4, arg5)); => new XamarinAppTypedSelector<object>(_source.Invoke(methodName, arg1, arg2, arg3, arg4, arg5));
IAppTypedSelector<TResult> IAppTypedSelector<T>.Value<TResult>() IAppTypedSelector<TResult> IAppTypedSelector<T>.Value<TResult>()
=> new XamarinAppTypedSelector<TResult>(_source.Value<TResult>()); => new XamarinAppTypedSelector<TResult>(_source.Value<object>());
} }
} }

Просмотреть файл

@ -21,6 +21,6 @@ namespace Uno.UITest.Xamarin
IAppQuery IPropertyAppQuery.StartsWith(string text) => _source.StartsWith(text).AsGenericAppQuery(); IAppQuery IPropertyAppQuery.StartsWith(string text) => _source.StartsWith(text).AsGenericAppQuery();
IAppTypedSelector<T> IPropertyAppQuery.Value<T>() => _source.Value<T>().AsGenericAppTypedSelector(); IAppTypedSelector<T> IPropertyAppQuery.Value<T>() => _source.Value<object>().AsGenericAppTypedSelector<T>();
} }
} }