[UWP] Update TestApp for interaction tests (#6039)
* Add skeleton of test app * Split app and unit test projects * Remove commented properties * Rename unittest file * Add certificate key * Add first smoke test * V1 * Add required panel for using internal libraries * Small refactor * Update tests * Remove extra files * Remove extra nuget feed * Add comments to test * Fix tests * Add comments for removed code to explain code duplicacy * Add instructions to run the tests * Update test to avoid breaking as time passes * Fix deploy on build * Change rendered card to be a field * Change source to own feed * Add instructions on adding new nuget packages * Update feed and instructions to push packages into it * Change retrieved inputs to be a textblock * Add troubleshoot section to ui test * Add scrollviewers for card and results
This commit is contained in:
Родитель
c23feeae6c
Коммит
6e75f69cc7
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<!-- remove any machine-wide sources with <clear/> -->
|
||||
<clear />
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
|
||||
<add key="AdaptiveCards-Public" value="https://pkgs.dev.azure.com/ms/AdaptiveCards/_packaging/AdaptiveCards-Public/nuget/v3/index.json" />
|
||||
</packageSources>
|
||||
<disabledPackageSources>
|
||||
<clear />
|
||||
|
|
|
@ -25,7 +25,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PerfApp", "PerfApp\PerfApp.
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UWPUITestApp", "UWPUITestApp\UWPUITestApp.csproj", "{1BDC51AF-4D95-44E3-92BD-BD1C8492C13D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UWPUITests", "UWPUITests\UWPUITests.csproj", "{C65B7488-ED39-4E9E-8A66-C53D72262660}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UWPUITests", "UWPUITests\UWPUITests.csproj", "{6958ADC8-DFF1-4446-9F15-E51F26782470}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AdaptiveCardsObjectModel", "AdaptiveCardsObjectModel\AdaptiveCardsObjectModel.vcxproj", "{29129512-A203-4718-BBED-EDAF7F4A02CD}"
|
||||
EndProject
|
||||
|
@ -222,6 +222,26 @@ Global
|
|||
{1BDC51AF-4D95-44E3-92BD-BD1C8492C13D}.Release|x86.ActiveCfg = Release|x86
|
||||
{1BDC51AF-4D95-44E3-92BD-BD1C8492C13D}.Release|x86.Build.0 = Release|x86
|
||||
{1BDC51AF-4D95-44E3-92BD-BD1C8492C13D}.Release|x86.Deploy.0 = Release|x86
|
||||
{6958ADC8-DFF1-4446-9F15-E51F26782470}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6958ADC8-DFF1-4446-9F15-E51F26782470}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6958ADC8-DFF1-4446-9F15-E51F26782470}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{6958ADC8-DFF1-4446-9F15-E51F26782470}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{6958ADC8-DFF1-4446-9F15-E51F26782470}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{6958ADC8-DFF1-4446-9F15-E51F26782470}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{6958ADC8-DFF1-4446-9F15-E51F26782470}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{6958ADC8-DFF1-4446-9F15-E51F26782470}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{6958ADC8-DFF1-4446-9F15-E51F26782470}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{6958ADC8-DFF1-4446-9F15-E51F26782470}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{6958ADC8-DFF1-4446-9F15-E51F26782470}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6958ADC8-DFF1-4446-9F15-E51F26782470}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6958ADC8-DFF1-4446-9F15-E51F26782470}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{6958ADC8-DFF1-4446-9F15-E51F26782470}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{6958ADC8-DFF1-4446-9F15-E51F26782470}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{6958ADC8-DFF1-4446-9F15-E51F26782470}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{6958ADC8-DFF1-4446-9F15-E51F26782470}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{6958ADC8-DFF1-4446-9F15-E51F26782470}.Release|x64.Build.0 = Release|Any CPU
|
||||
{6958ADC8-DFF1-4446-9F15-E51F26782470}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{6958ADC8-DFF1-4446-9F15-E51F26782470}.Release|x86.Build.0 = Release|Any CPU
|
||||
{C65B7488-ED39-4E9E-8A66-C53D72262660}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C65B7488-ED39-4E9E-8A66-C53D72262660}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C65B7488-ED39-4E9E-8A66-C53D72262660}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
|
|
|
@ -12,4 +12,33 @@ Since Adaptive Cards are hosted directly within the Windows OS we had implementa
|
|||
|
||||
## How to test
|
||||
|
||||
To run the test project, see the [AdaptiveCardTestApp](AdaptiveCardTestApp/README.md) folder
|
||||
To run the test project, see the [AdaptiveCardTestApp](AdaptiveCardTestApp/README.md) folder
|
||||
|
||||
## How to add a new NuGet package
|
||||
|
||||
Due to limitations in our build system and Test infrastructure libraries used for UI tests, the process to add new NuGet packages has changed. The new process requires us to push any NuGet packages to a new NuGet feed called `AdaptiveCards-public` where we can have packages that come from any number of sources.
|
||||
|
||||
### Adding / Updating a new NuGet package locally
|
||||
|
||||
To add or update a NuGet package locally you have to add `nuget.org` as a NuGet package source:
|
||||
|
||||
1. Add the following line to the NuGet.config file located under `AdaptiveCards/source/`:
|
||||
|
||||
``` <add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" /> ```
|
||||
|
||||
2. Restart Visual Studio to load the changes
|
||||
|
||||
### Pushing the NuGet package to the AdaptiveCards-public feed
|
||||
|
||||
Once the new package has been tested locally and is ready to be merged:
|
||||
|
||||
1. If you already have NuGet, you can skip to step 3, otherwise download the [lastest NuGet version](https://www.nuget.org/downloads)
|
||||
2. [Optional] Add the nuget.exe location to the PATH environment variable
|
||||
3. Open Visual Studio and start a Package Manager Console (Tools -> NuGet Package Manager -> Package Manager Console)
|
||||
4. Manually push any nuget packages you added by typing the following into the Package manager console:
|
||||
|
||||
``` nuget.exe push -Source "AdaptiveCards-Public" -ApiKey az <PackagePath\PackageName.nupkg> -SkipDuplicate```
|
||||
|
||||
> * You may be prompted to login before pushing any NuGet packages into the public feed
|
||||
>
|
||||
> * Downloaded NuGet packages are usually located at `C:\Users\<UserName>\.nuget\packages`
|
|
@ -0,0 +1,37 @@
|
|||
<Page
|
||||
x:Class="UWPUITestApp.CardPresenter"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:UWPUITestApp"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
|
||||
<Grid>
|
||||
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="600"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="100" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<ScrollViewer Height="500" Width="600" HorizontalScrollBarVisibility="Disabled"
|
||||
VerticalScrollBarVisibility="Auto" Grid.Column="0" Grid.Row="0">
|
||||
<Grid x:Name="GridContainer" />
|
||||
</ScrollViewer>
|
||||
|
||||
<Grid Grid.Column="0" Grid.Row="1" Background="LightGray">
|
||||
<ScrollViewer Height="100" Width="600" HorizontalScrollBarVisibility="Disabled"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
<TextBlock Text="" AutomationProperties.Name="RetrievedInputs_TextBlock"
|
||||
x:Name="RetrievedInputs_TextBlock"
|
||||
TextWrapping="WrapWholeWords" />
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
</Page>
|
|
@ -0,0 +1,106 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
using System;
|
||||
using Windows.ApplicationModel;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Storage;
|
||||
using AdaptiveCards.Rendering.Uwp;
|
||||
using System.Collections.ObjectModel;
|
||||
using AdaptiveCards.ObjectModel.Uwp;
|
||||
|
||||
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
|
||||
|
||||
namespace UWPUITestApp
|
||||
{
|
||||
/// <summary>
|
||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||
/// </summary>
|
||||
public sealed partial class CardPresenter : Page
|
||||
{
|
||||
private static CardPresenter _Instance = null;
|
||||
public static CardPresenter Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_Instance == null)
|
||||
{
|
||||
_Instance = new CardPresenter();
|
||||
}
|
||||
|
||||
return _Instance;
|
||||
}
|
||||
}
|
||||
|
||||
private string _TestCase = "";
|
||||
|
||||
public string TestCase
|
||||
{
|
||||
get
|
||||
{
|
||||
return _TestCase;
|
||||
}
|
||||
set
|
||||
{
|
||||
_TestCase = value;
|
||||
RenderAdaptiveCardAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<Tuple<string, string>> Inputs = new ObservableCollection<Tuple<string, string>>();
|
||||
|
||||
private MainPage MainPage = null;
|
||||
|
||||
private RenderedAdaptiveCard RenderedCard = null;
|
||||
|
||||
private CardPresenter()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
internal void SetMainWindow(MainPage mainPage)
|
||||
{
|
||||
MainPage = mainPage;
|
||||
}
|
||||
|
||||
internal async Task RenderAdaptiveCardAsync()
|
||||
{
|
||||
CleanRetrievedInputs();
|
||||
|
||||
string adaptiveCardContents = await ReadTestCaseContentsAsync(TestCase);
|
||||
var renderer = new AdaptiveCardRenderer();
|
||||
AdaptiveCard card = AdaptiveCard.FromJsonString(adaptiveCardContents).AdaptiveCard;
|
||||
RenderedCard = renderer.RenderAdaptiveCard(card);
|
||||
|
||||
RenderedCard.Action += RenderedCard_Action;
|
||||
|
||||
GridContainer.Children.Clear();
|
||||
GridContainer.Children.Add(RenderedCard.FrameworkElement);
|
||||
}
|
||||
|
||||
private void RenderedCard_Action(RenderedAdaptiveCard sender, AdaptiveActionEventArgs args)
|
||||
{
|
||||
CleanRetrievedInputs();
|
||||
|
||||
if (args.Action.ActionType == ActionType.Submit)
|
||||
{
|
||||
RetrievedInputs_TextBlock.Text = sender.UserInputs.AsJson().ToString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void CleanRetrievedInputs()
|
||||
{
|
||||
RetrievedInputs_TextBlock.Text = "";
|
||||
}
|
||||
|
||||
private async Task<string> ReadTestCaseContentsAsync(string testCase)
|
||||
{
|
||||
var testcasesFolder = await Package.Current.InstalledLocation.GetFolderAsync("LinkedTestCards");
|
||||
var testCaseFile = await testcasesFolder.GetFileAsync(testCase + ".json");
|
||||
var contents = await FileIO.ReadTextAsync(testCaseFile);
|
||||
return contents;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,10 +6,38 @@
|
|||
xmlns:local="using:UWPUITestApp"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:testhelpers="using:AppTestAutomationHelpers"
|
||||
mc:Ignorable="d"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
|
||||
<Grid>
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="1" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<testhelpers:TestAutomationHelpersPanel Grid.Row="0"/>
|
||||
|
||||
<Grid Grid.Row="1" Margin="0, 20, 0, 0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Button x:Name="HomeButton" AutomationProperties.Name="HomeButton" Content="Home"
|
||||
Click="HomeButton_Click" Grid.Column="0" Visibility="Collapsed" />
|
||||
<TextBlock x:Name="TitleTextBlock" AutomationProperties.Name="TitleTextBlock"
|
||||
Text="Home" FontSize="20" Grid.Column="1" HorizontalAlignment="Center" Height="27" VerticalAlignment="Bottom" />
|
||||
|
||||
</Grid>
|
||||
|
||||
<Grid Grid.Row="2">
|
||||
<StackPanel Width="600" Height="600">
|
||||
<ContentPresenter x:Name="PagePresenter" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
</Page>
|
||||
|
|
|
@ -1,19 +1,7 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Controls.Primitives;
|
||||
using Windows.UI.Xaml.Data;
|
||||
using Windows.UI.Xaml.Input;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
|
||||
|
||||
|
@ -27,6 +15,30 @@ namespace UWPUITestApp
|
|||
public MainPage()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
|
||||
TestCaseListPresenter.Instance.SetContainer(this);
|
||||
CardPresenter.Instance.SetMainWindow(this);
|
||||
|
||||
PagePresenter.Content = TestCaseListPresenter.Instance;
|
||||
}
|
||||
|
||||
internal void ItemClicked(string testCaseName)
|
||||
{
|
||||
CardPresenter.Instance.TestCase = testCaseName;
|
||||
PagePresenter.Content = CardPresenter.Instance;
|
||||
HomeButton.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
private void HomeButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
PagePresenter.Content = TestCaseListPresenter.Instance;
|
||||
TitleTextBlock.Text = "Home";
|
||||
HomeButton.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
internal void UpdateTitle(string newTitle)
|
||||
{
|
||||
TitleTextBlock.Text = newTitle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
<Properties>
|
||||
<DisplayName>UWPUITestApp</DisplayName>
|
||||
<PublisherDisplayName>almedina</PublisherDisplayName>
|
||||
<PublisherDisplayName>Microsoft Corporation</PublisherDisplayName>
|
||||
<Logo>Assets\StoreLogo.png</Logo>
|
||||
</Properties>
|
||||
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
<Page
|
||||
x:Class="UWPUITestApp.TestCaseListPresenter"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:UWPUITestApp"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
|
||||
<Grid>
|
||||
|
||||
<ScrollViewer HorizontalAlignment="Center" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled">
|
||||
<ItemsControl ItemsSource="{x:Bind TestCases}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<ItemsWrapGrid Orientation="Vertical"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Button
|
||||
AutomationProperties.Name="{Binding}"
|
||||
Content="{Binding}"
|
||||
FontSize="20"
|
||||
Margin="0,0,12,12"
|
||||
VerticalAlignment="Stretch"
|
||||
Click="Button_Click" />
|
||||
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
|
||||
</Grid>
|
||||
</Page>
|
|
@ -0,0 +1,80 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.ApplicationModel;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Controls.Primitives;
|
||||
using Windows.UI.Xaml.Data;
|
||||
using Windows.UI.Xaml.Input;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
|
||||
|
||||
namespace UWPUITestApp
|
||||
{
|
||||
/// <summary>
|
||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||
/// </summary>
|
||||
public sealed partial class TestCaseListPresenter : Page
|
||||
{
|
||||
|
||||
private static TestCaseListPresenter _Instance = null;
|
||||
public static TestCaseListPresenter Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_Instance == null)
|
||||
{
|
||||
_Instance = new TestCaseListPresenter();
|
||||
}
|
||||
|
||||
return _Instance;
|
||||
}
|
||||
}
|
||||
|
||||
public MainPage MainPage { get; set; }
|
||||
|
||||
public ObservableCollection<string> TestCases { get; set; } = new ObservableCollection<string>();
|
||||
|
||||
public TestCaseListPresenter()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
|
||||
LoadTestCasesAsync();
|
||||
}
|
||||
|
||||
internal void SetContainer(MainPage mainPage)
|
||||
{
|
||||
MainPage = mainPage;
|
||||
}
|
||||
|
||||
private void Button_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
string buttonContent = (sender as Button)?.Content.ToString();
|
||||
|
||||
MainPage.UpdateTitle(buttonContent);
|
||||
MainPage.ItemClicked(buttonContent);
|
||||
}
|
||||
|
||||
private async Task LoadTestCasesAsync()
|
||||
{
|
||||
var testCasesFolder = await Package.Current.InstalledLocation.GetFolderAsync("LinkedTestCards");
|
||||
|
||||
foreach (var file in await testCasesFolder.GetFilesAsync())
|
||||
{
|
||||
TestCases.Add(file.Name.Replace(".json", ""));
|
||||
}
|
||||
|
||||
UpdateLayout();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,6 +18,7 @@
|
|||
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<WindowsXamlEnableOverview>true</WindowsXamlEnableOverview>
|
||||
<AppxPackageSigningEnabled>True</AppxPackageSigningEnabled>
|
||||
<GenerateAppxPackageOnBuild>True</GenerateAppxPackageOnBuild>
|
||||
<PackageCertificateThumbprint>571260330A6015C25387D6A440FB552DF3964EA1</PackageCertificateThumbprint>
|
||||
<PackageCertificateKeyFile>UWPUITestApp_TemporaryKey.pfx</PackageCertificateKeyFile>
|
||||
</PropertyGroup>
|
||||
|
@ -121,10 +122,16 @@
|
|||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="CardPresenter.xaml.cs">
|
||||
<DependentUpon>CardPresenter.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="MainPage.xaml.cs">
|
||||
<DependentUpon>MainPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="TestCaseListPresenter.xaml.cs">
|
||||
<DependentUpon>TestCaseListPresenter.xaml</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AppxManifest Include="Package.appxmanifest">
|
||||
|
@ -146,23 +153,63 @@
|
|||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Page Include="CardPresenter.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="MainPage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="TestCaseListPresenter.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
|
||||
<Version>6.2.11</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="MUXAppTestHelpers">
|
||||
<Version>0.0.4</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\..\samples\v1.0\Scenarios\ActivityUpdate.json">
|
||||
<Link>LinkedTestCards\ActivityUpdate.json</Link>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="..\..\..\samples\v1.3\Elements\Input.Text.ErrorMessage.json">
|
||||
<Link>LinkedTestCards\Input.Text.ErrorMessage.json</Link>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="..\..\..\samples\v1.5\Scenarios\InputFormWithLabels.json">
|
||||
<Link>LinkedTestCards\InputFormWithLabels.json</Link>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="UWPUITestApp_TemporaryKey.pfx" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AdaptiveCardsObjectModel\AdaptiveCardsObjectModel.vcxproj">
|
||||
<Project>{29129512-a203-4718-bbed-edaf7f4a02cd}</Project>
|
||||
<Name>AdaptiveCardsObjectModel</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Renderer\AdaptiveCardRenderer.vcxproj">
|
||||
<Project>{cf169157-f487-420c-8b9b-ca3abe2bb209}</Project>
|
||||
<Name>AdaptiveCardRenderer</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '14.0' ">
|
||||
<VisualStudioVersion>14.0</VisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
|
|
|
@ -5,7 +5,6 @@ using System;
|
|||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Management.Deployment;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
@ -16,47 +15,75 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|||
using Microsoft.VisualStudio.TestTools.UnitTesting.Logging;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
using OpenQA.Selenium.Appium;
|
||||
using Windows.Foundation;
|
||||
using Windows.Management.Deployment;
|
||||
using Microsoft.Windows.Apps.Test.Foundation;
|
||||
using Microsoft.Windows.Apps.Test.Foundation.Controls;
|
||||
using Microsoft.Windows.Apps.Test.Foundation.Waiters;
|
||||
using Microsoft.Windows.Apps.Test.Automation;
|
||||
|
||||
namespace UWPUITests
|
||||
{
|
||||
using Window = Microsoft.Windows.Apps.Test.Foundation.Controls.Window;
|
||||
|
||||
// Most of this code is part of the MUX Testing Infrastructure,
|
||||
// investigation on the added packages must be made to verify if there's any API that can do the same
|
||||
// TODO: Verify if the MUXTestInfra package can be used, instead of duplicating their code (Issue #6052)
|
||||
public class Application
|
||||
{
|
||||
protected const string WindowsApplicationDriverUrl = "http://127.0.0.1:4723/wd/hub";
|
||||
private WindowsDriver<WindowsElement> TestAppSession = null;
|
||||
|
||||
private readonly string _simplePackageName;
|
||||
|
||||
private readonly string _packageName;
|
||||
private readonly string _packageFamilyName;
|
||||
private readonly string _appName;
|
||||
private readonly string _appWindowTitle;
|
||||
|
||||
private readonly string _certSerialNumber;
|
||||
private readonly string _baseAppxDir;
|
||||
|
||||
public Application()
|
||||
private readonly UICondition _windowCondition = null;
|
||||
private readonly UICondition _appFrameWindowCondition = null;
|
||||
|
||||
private static Application _Instance = null;
|
||||
|
||||
public static Application Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_Instance == null)
|
||||
{
|
||||
_Instance = new Application();
|
||||
}
|
||||
return _Instance;
|
||||
}
|
||||
}
|
||||
|
||||
private Application()
|
||||
{
|
||||
_simplePackageName = "UWPUITestApp";
|
||||
|
||||
_packageName = "AdaptiveCardsUWPUITestApp";
|
||||
_packageFamilyName = "AdaptiveCardsUWPUITestApp_ghhk6r1bdgbcc";
|
||||
_appName = "AdaptiveCardsUWPUITestApp_ghhk6r1bdgbcc!App";
|
||||
_appWindowTitle = "UWPUITestApp";
|
||||
|
||||
_certSerialNumber = "55caf56ff51d839e482b7c988be2c263";
|
||||
|
||||
string assemblyDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
string baseDirectory = Directory.GetParent(assemblyDir).Parent.FullName;
|
||||
string baseDirectory = Directory.GetParent(assemblyDir).Parent.Parent.FullName;
|
||||
|
||||
// Replace the TestLibrary folder for the TestApp folder
|
||||
string appBaseDirectory = baseDirectory.Replace("UWPUITestLibrary", "UWPUITestApp");
|
||||
string appBaseDirectory = baseDirectory.Replace("UWPUITests", "UWPUITestApp");
|
||||
|
||||
_baseAppxDir = appBaseDirectory;
|
||||
|
||||
_windowCondition = UICondition.Create("@ClassName='Window' AND @Name={0}", _appWindowTitle);
|
||||
_appFrameWindowCondition = UICondition.Create("@ClassName='Window' AND @Name={0}", _appWindowTitle);
|
||||
}
|
||||
|
||||
#region Properties
|
||||
public UIObject CoreWindow { get; private set; }
|
||||
public UIObject ApplicationFrameWindow { get; private set; }
|
||||
public Process Process { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
@ -64,48 +91,185 @@ namespace UWPUITests
|
|||
#region Methods
|
||||
internal void Initialize(bool doLaunch = false, string deploymentDir = null)
|
||||
{
|
||||
if (TestAppSession == null)
|
||||
var topWindowCondition = _windowCondition.OrWith(_appFrameWindowCondition);
|
||||
|
||||
UIObject topWindowObj = null;
|
||||
bool didFindWindow = UIObject.Root.Children.TryFind(topWindowCondition, out topWindowObj);
|
||||
|
||||
// Only try to launch the app if we couldn't find the window.
|
||||
if (!didFindWindow)
|
||||
{
|
||||
TestAppSession = Launch();
|
||||
CoreWindow = Launch();
|
||||
|
||||
foreach (UIObject obj in CoreWindow.Ancestors)
|
||||
{
|
||||
if (obj.Matches(_appFrameWindowCondition))
|
||||
{
|
||||
ApplicationFrameWindow = CoreWindow.Parent;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (didFindWindow)
|
||||
{
|
||||
// topWindowObj should match either _windowCondition or _appFrameWindowCondition
|
||||
|
||||
if (topWindowObj.Matches(_windowCondition))
|
||||
{
|
||||
// If the top level window is CoreWindow, then there is no AppFrame window:
|
||||
CoreWindow = topWindowObj;
|
||||
ApplicationFrameWindow = null;
|
||||
}
|
||||
else // _appFrameWindowCondition
|
||||
{
|
||||
if (!topWindowObj.Matches(_appFrameWindowCondition))
|
||||
{
|
||||
}
|
||||
|
||||
// Maxmize window to ensure we can find UIA elements
|
||||
var appFrameWindow = new Window(topWindowObj);
|
||||
if (appFrameWindow.CanMaximize)
|
||||
{
|
||||
appFrameWindow.SetWindowVisualState(WindowVisualState.Maximized);
|
||||
}
|
||||
|
||||
Assert.IsTrue(topWindowObj.Matches(_appFrameWindowCondition));
|
||||
ApplicationFrameWindow = topWindowObj;
|
||||
|
||||
Logger.LogMessage("Looking for CoreWindow...");
|
||||
for (int retries = 0; retries < 5; ++retries)
|
||||
{
|
||||
if (topWindowObj.Children.TryFind(_windowCondition, out var coreWindowObject))
|
||||
{
|
||||
CoreWindow = coreWindowObject;
|
||||
Logger.LogMessage("Found CoreWindow.");
|
||||
break;
|
||||
}
|
||||
|
||||
Logger.LogMessage("CoreWindow not found. Sleep for 500 ms and retry");
|
||||
Thread.Sleep(500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (CoreWindow == null)
|
||||
{
|
||||
// We expect to have a window by this point.
|
||||
// LogDumpTree();
|
||||
throw new UIObjectNotFoundException("Could not find application window.");
|
||||
}
|
||||
|
||||
// If this is running on desktop (it has an app frame window) then try to
|
||||
// maximize the window.
|
||||
|
||||
if (ApplicationFrameWindow != null)
|
||||
{
|
||||
var appFrameWindow = new Window(ApplicationFrameWindow);
|
||||
if (appFrameWindow.CanMaximize)
|
||||
{
|
||||
appFrameWindow.SetWindowVisualState(WindowVisualState.Maximized);
|
||||
}
|
||||
}
|
||||
|
||||
Process = Process.GetProcessById(CoreWindow.ProcessId);
|
||||
}
|
||||
|
||||
private WindowsDriver<WindowsElement> Launch()
|
||||
private UIObject Launch()
|
||||
{
|
||||
WindowsDriver<WindowsElement> testAppSession = null;
|
||||
UIObject coreWindow = null;
|
||||
|
||||
InstallTestAppIfNeeded();
|
||||
|
||||
Logger.LogMessage("Launching app {0}", _appName);
|
||||
|
||||
testAppSession = LaunchApp();
|
||||
coreWindow = LaunchApp();
|
||||
|
||||
Assert.IsNotNull(testAppSession, "coreWindow");
|
||||
Assert.IsNotNull(coreWindow, "coreWindow");
|
||||
|
||||
return testAppSession;
|
||||
Logger.LogMessage("Waiting for the close-app invoker to be found to signal that the app has launched successfully...");
|
||||
|
||||
for (int retries = 0; retries < 5; ++retries)
|
||||
{
|
||||
UIObject obj;
|
||||
coreWindow.Descendants.TryFind(UICondition.Create("@AutomationId='__CloseAppInvoker'"), out obj);
|
||||
if (obj != null)
|
||||
{
|
||||
Logger.LogMessage("Invoker found!");
|
||||
break;
|
||||
}
|
||||
|
||||
Logger.LogMessage("Invoker not found. Sleeping for 500 ms before trying again...");
|
||||
Thread.Sleep(500);
|
||||
}
|
||||
|
||||
Logger.LogMessage("15056441 tracing, device family:" + Windows.System.Profile.AnalyticsInfo.VersionInfo.DeviceFamily);
|
||||
|
||||
return coreWindow;
|
||||
}
|
||||
|
||||
private WindowsDriver<WindowsElement> LaunchApp()
|
||||
private UIObject LaunchApp()
|
||||
{
|
||||
AppiumOptions options = new AppiumOptions();
|
||||
options.AddAdditionalCapability("platformName", "Windows");
|
||||
options.AddAdditionalCapability("platformVersion", "10");
|
||||
options.AddAdditionalCapability("deviceName", "WindowsPC");
|
||||
UIObject coreWindow = null;
|
||||
|
||||
// Update this value
|
||||
options.AddAdditionalCapability("app", _appName);
|
||||
// Launch sometimes times out but the app is just slow to launch and Launch has what appears to be
|
||||
// a 5-second timeout built in. 5 seconds isn't always enough in VM scenarios. If we try again,
|
||||
// Launch will see that the app is already running and move on.
|
||||
const int MaxLaunchRetries = 5;
|
||||
for (int retries = 1; retries <= MaxLaunchRetries; ++retries)
|
||||
{
|
||||
try
|
||||
{
|
||||
Logger.LogMessage("Attempting launch, try #{0}...", retries);
|
||||
coreWindow = LaunchUWPApp();
|
||||
Logger.LogMessage("Launch successful!");
|
||||
break;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogMessage("Failed to launch app. Exception: " + ex.ToString());
|
||||
|
||||
WindowsDriver<WindowsElement> testAppSession = new WindowsDriver<WindowsElement>(new Uri(WindowsApplicationDriverUrl), options);
|
||||
if (retries < MaxLaunchRetries)
|
||||
{
|
||||
Logger.LogMessage("UAPApp.Launch might not have waited long enough, trying again {0}", retries);
|
||||
Thread.Sleep(TimeSpan.FromSeconds(10)); // Give a healthy wait time.
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogMessage("Dumping UIA tree...");
|
||||
// LogDumpTree();
|
||||
Logger.LogMessage("Could not launch app {0} with top-level window condition '{1}'!", _appName, CreateTopLevelWindowCondition().ToString());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return testAppSession;
|
||||
return coreWindow;
|
||||
}
|
||||
|
||||
private UIObject LaunchUWPApp()
|
||||
{
|
||||
var nameCondition = UICondition.CreateFromName(_appWindowTitle);
|
||||
var topLevelWindowCondition = CreateTopLevelWindowCondition().AndWith(nameCondition);
|
||||
return UAPApp.Launch(_appName, topLevelWindowCondition);
|
||||
}
|
||||
|
||||
private UICondition CreateTopLevelWindowCondition()
|
||||
{
|
||||
string deviceFamily = Windows.System.Profile.AnalyticsInfo.VersionInfo.DeviceFamily;
|
||||
if (deviceFamily.Equals("Windows.Desktop", StringComparison.OrdinalIgnoreCase)
|
||||
|| deviceFamily.Equals("Windows.Server", StringComparison.OrdinalIgnoreCase)
|
||||
|| deviceFamily.Equals("Windows.Team", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return UICondition.CreateFromClassName("ApplicationFrameWindow");
|
||||
}
|
||||
else
|
||||
{
|
||||
return UICondition.CreateFromClassName("Windows.UI.Core.CoreWindow");
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if (TestAppSession != null)
|
||||
{
|
||||
TestAppSession.Quit();
|
||||
}
|
||||
}
|
||||
|
||||
// This is a slightly modified version of how WinUI remove a previously installed version of the test app, as Appium is not
|
||||
|
@ -145,7 +309,7 @@ namespace UWPUITests
|
|||
foreach (var installedPackage in installedPackages)
|
||||
{
|
||||
Logger.LogMessage("Test AppX package already installed. Removing existing package by name: {0}", installedPackage.Id.FullName);
|
||||
|
||||
|
||||
AutoResetEvent removePackageCompleteEvent = new AutoResetEvent(false);
|
||||
|
||||
var removeAppPowershellProcess = Process.Start(new ProcessStartInfo("powershell",
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
[assembly: AssemblyTitle("UWPUITestLibrary")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("UWPUITestLibrary")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2021")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
[assembly: Guid("c65b7488-ed39-4e9e-8a66-c53d72262660")]
|
||||
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -0,0 +1,25 @@
|
|||
# Running Automation Tests Locally
|
||||
|
||||
## Before running the tests
|
||||
|
||||
Before running the tests the WinUITestApp must be built and the appx package that will be installed for testing must be generated, this can be done by building the project in VisualStudio, but if the package was not generated you can follow the steps below to generate the package:
|
||||
|
||||
1. Open a "Developer Command Prompt for VS 2019"
|
||||
2. From the AdaptiveCards repository root: ` cd source\uwp\UWPUITestApp `
|
||||
3. Build the appx package by executing the command ` msbuild .\UWPUITestApp.csproj /p:DeployOnBuild=true `
|
||||
|
||||
## Executing the tests
|
||||
|
||||
Tests can be executed from Visual studio by running them as any other unit test, you can look for them in the Test explorer. Executing the tests require the system to install the appx package built on the previous steps, you may require to provide permissions for the certificate to be installed.
|
||||
|
||||
## Troubleshoot
|
||||
|
||||
### The TestApp is not being initialized
|
||||
|
||||
The UI tests require the UI TestApp to be installed in the system, the installation process is done automatically when tests are run but the UITestApp should be built before tests are run. This is required for generating the required Appx files to be used for installing the application.
|
||||
|
||||
Another possible problem for the installation may be provoked from having an application with the same ID installed from an outside source, this can be fixed by finding the application with the same ID and uninstalling it by executing `Remove-AppxPackage -Package "<package_id>"`.
|
||||
|
||||
### Display Scale
|
||||
|
||||
The framework used for interacting with the TestApp does not support having a display scale factor different than 100%, you can check the value of this property by going to `System > Display`
|
|
@ -0,0 +1,190 @@
|
|||
using Microsoft.Windows.Apps.Test.Foundation;
|
||||
using Microsoft.Windows.Apps.Test.Foundation.Controls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace UWPUITests
|
||||
{
|
||||
public class TestHelpers
|
||||
{
|
||||
|
||||
public static UIObject FindDescendantBy(string propertyName, string value, UIObject parent)
|
||||
{
|
||||
return parent.Descendants.Find(UIProperty.Get(propertyName), value);
|
||||
}
|
||||
|
||||
public static UIObject FindElementByName(string name)
|
||||
{
|
||||
return FindDescendantBy("Name", name, Application.Instance.CoreWindow);
|
||||
}
|
||||
|
||||
public static UIObject FindElementByClassName(string classname)
|
||||
{
|
||||
return FindDescendantBy("ClassName", classname, Application.Instance.CoreWindow);
|
||||
}
|
||||
|
||||
public static UIObject FindElementByAutomationId(string automationId)
|
||||
{
|
||||
return FindDescendantBy("AutomationId", automationId, Application.Instance.CoreWindow);
|
||||
}
|
||||
|
||||
public static UIObject FindElementByName(string name, UIObject parent)
|
||||
{
|
||||
return FindDescendantBy("Name", name, parent);
|
||||
}
|
||||
|
||||
public static UIObject FindElementByClassName(string classname, UIObject parent)
|
||||
{
|
||||
return FindDescendantBy("ClassName", classname, parent);
|
||||
}
|
||||
|
||||
public static UIObject FindElementByAutomationId(string automationId, UIObject parent)
|
||||
{
|
||||
return FindDescendantBy("AutomationId", automationId, parent);
|
||||
}
|
||||
|
||||
public static UIObject FindFlyoutByAutomationId(string automationId)
|
||||
{
|
||||
UIObject flyout = null;
|
||||
|
||||
try
|
||||
{
|
||||
flyout = Application.Instance.CoreWindow.Parent.Descendants.Find(automationId);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
for (int i = 0; i < 5 && flyout == null; ++i)
|
||||
{
|
||||
try
|
||||
{
|
||||
flyout = Application.Instance.CoreWindow.Parent.Descendants.Find(automationId);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// wait 500 ms while the flyout is not found
|
||||
Thread.Sleep(500);
|
||||
}
|
||||
}
|
||||
}
|
||||
return flyout;
|
||||
}
|
||||
|
||||
public static UIObject FindByMultiple(params object[] list)
|
||||
{
|
||||
var filteredList = Application.Instance.CoreWindow.Descendants;
|
||||
|
||||
for (int i = 0; (i + 1) < list.Length && filteredList.Count > 1; i += 2)
|
||||
{
|
||||
string propertyName = list[i] as string;
|
||||
string value = list[i + 1] as string;
|
||||
filteredList = filteredList.FindMultiple(UIProperty.Get(propertyName), value);
|
||||
}
|
||||
|
||||
return filteredList.Count > 0 ? filteredList[0] : null;
|
||||
}
|
||||
|
||||
public static void GoToTestCase(string testCaseName)
|
||||
{
|
||||
var application = Application.Instance.CoreWindow;
|
||||
|
||||
// If we are not in the home screen then we go to home and then click on the TestCase
|
||||
if (GetTitleText() != "Home")
|
||||
{
|
||||
FindElementByName("HomeButton")?.Click();
|
||||
}
|
||||
|
||||
FindElementByName(testCaseName)?.Click();
|
||||
|
||||
if (GetTitleText() != testCaseName)
|
||||
{
|
||||
throw new Exception("TestCase " + testCaseName + "could not be initialized");
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetTitleText()
|
||||
{
|
||||
var uiObject = FindElementByName("TitleTextBlock");
|
||||
TextBlock titleTextBlock = CastTo<TextBlock>(uiObject);
|
||||
return titleTextBlock?.DocumentText;
|
||||
}
|
||||
|
||||
public static string GetInputValue(string inputId)
|
||||
{
|
||||
var inputTextBlock = CastTo<TextBlock>(FindElementByName("RetrievedInputs_TextBlock"));
|
||||
Assert.IsNotNull(inputTextBlock, "Failed to retrieve retrieved inputs text block");
|
||||
|
||||
string retrivedInputsJsonString = inputTextBlock.DocumentText;
|
||||
var retrievedInputs = JsonConvert.DeserializeObject<Dictionary<string, string>>(retrivedInputsJsonString);
|
||||
|
||||
return retrievedInputs[inputId];
|
||||
|
||||
// var inputTextBlock = CastTo<TextBlock>(FindElementByName(inputId + "_retrievedValue"));
|
||||
// return inputTextBlock?.DocumentText;
|
||||
}
|
||||
|
||||
public static void SetDateToUIElement(int year, int month, int day)
|
||||
{
|
||||
// Retrieve the date input and click on it
|
||||
// TODO: Fix UWP implementation to assign name/id to the CalendarDatePicker control
|
||||
var dateInput = FindElementByClassName("CalendarDatePicker");
|
||||
dateInput.Click();
|
||||
|
||||
// Retrieve the popup which contains the calendar view
|
||||
var calendarView = FindFlyoutByAutomationId("CalendarView");
|
||||
|
||||
UIObject headerButton = CastTo<Button>(FindElementByAutomationId("HeaderButton", calendarView));
|
||||
string[] monthAndYear = headerButton.Name.Split(" ");
|
||||
|
||||
// The CalendarDatePicker control adds a character 8206 to each end of the month name,
|
||||
// so we have to remove them before looking up for the month number
|
||||
int currentMonth = MonthNameToInt(monthAndYear[0]);
|
||||
MoveToMonth(currentMonth, month, calendarView);
|
||||
|
||||
// Click on the day "16" button which in turn closes the popup
|
||||
FindElementByName("16", calendarView).Click();
|
||||
}
|
||||
|
||||
private static void MoveToMonth(int currentMonth, int expectedMonth, UIObject calendarView)
|
||||
{
|
||||
if (currentMonth < expectedMonth)
|
||||
{
|
||||
UIObject nextButton = FindElementByAutomationId("NextButton", calendarView);
|
||||
while (currentMonth != expectedMonth)
|
||||
{
|
||||
nextButton.Click();
|
||||
currentMonth++;
|
||||
}
|
||||
}
|
||||
if (currentMonth > expectedMonth)
|
||||
{
|
||||
UIObject previousButton = FindElementByAutomationId("PreviousButton", calendarView);
|
||||
while (currentMonth != expectedMonth)
|
||||
{
|
||||
previousButton.Click();
|
||||
currentMonth--;
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for the scrolling animation to end
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
|
||||
static int MonthNameToInt(string monthName)
|
||||
{
|
||||
monthName = monthName.Substring(1, monthName.Length - 2);
|
||||
return DateTime.ParseExact(monthName, "MMMM", CultureInfo.CurrentCulture).Month;
|
||||
}
|
||||
|
||||
public static T CastTo<T>(UIObject uiObject)
|
||||
{
|
||||
return (T)Activator.CreateInstance(typeof(T), uiObject);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Microsoft.Windows.Apps.Test.Foundation;
|
||||
using Microsoft.Windows.Apps.Test.Foundation.Controls;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Windows.UI.Xaml.Tests.MUXControls.InteractionTests.Common;
|
||||
|
||||
namespace UWPUITests
|
||||
{
|
||||
|
@ -13,14 +15,53 @@ namespace UWPUITests
|
|||
[ClassInitialize]
|
||||
public static void Setup(TestContext testContext)
|
||||
{
|
||||
application = new Application();
|
||||
application = Application.Instance;
|
||||
application.Initialize();
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void TestMethod1()
|
||||
public void ActivityUpdateSmokeTest()
|
||||
{
|
||||
Assert.IsTrue(true);
|
||||
TestHelpers.GoToTestCase("ActivityUpdate");
|
||||
|
||||
// Retrieve the "Set due date" Button and click it
|
||||
var showCardButton = TestHelpers.FindElementByName("Set due date");
|
||||
Assert.IsNotNull(showCardButton, "Could not find 'Set due date' button");
|
||||
showCardButton.Click();
|
||||
|
||||
// Set the date on the Date control
|
||||
TestHelpers.SetDateToUIElement(2021, 07, 16);
|
||||
|
||||
// Retrieve the "Add a comment" Input.Text and fill it with information
|
||||
var commentTextBox = TestHelpers.CastTo<Edit>(TestHelpers.FindElementByName("Add a comment"));
|
||||
commentTextBox.SendKeys("A comment");
|
||||
|
||||
// Submit data
|
||||
TestHelpers.FindElementByName("OK").Click();
|
||||
|
||||
// Verify submitted data
|
||||
Assert.AreEqual("A comment", TestHelpers.GetInputValue("comment"), "Values for input comment differ");
|
||||
Assert.AreEqual("2021-07-16", TestHelpers.GetInputValue("dueDate"), "Values for input dueDate differ");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void InputTextValidationFailsForEmptyRequiredInputTest()
|
||||
{
|
||||
TestHelpers.GoToTestCase("Input.Text.ErrorMessage");
|
||||
|
||||
// Click on 'Submit' button
|
||||
var showCardButton = TestHelpers.FindElementByName("Submit");
|
||||
Assert.IsNotNull(showCardButton, "Could not find 'Submit' button");
|
||||
showCardButton.Click();
|
||||
|
||||
// Find the 'Required Input.Text' Input.Text,
|
||||
// as both the Label and the TextBox share the same name we have to discern between them
|
||||
var requiredInputTextBox = TestHelpers.FindByMultiple(
|
||||
"Name", "Required Input.Text *\r\n",
|
||||
"ClassName", "TextBox");
|
||||
|
||||
// Verify the retrieved Input.Text has the keyboard focus
|
||||
Assert.IsTrue(requiredInputTextBox.HasKeyboardFocus, "The first textblock did not get focus");
|
||||
}
|
||||
|
||||
[ClassCleanup]
|
||||
|
|
|
@ -1,92 +1,25 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\packages\MSTest.TestAdapter.2.1.2\build\net45\MSTest.TestAdapter.props" Condition="Exists('..\packages\MSTest.TestAdapter.2.1.2\build\net45\MSTest.TestAdapter.props')" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{C65B7488-ED39-4E9E-8A66-C53D72262660}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>UWPUITests</RootNamespace>
|
||||
<AssemblyName>UWPUITests</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
|
||||
<IsCodedUITest>False</IsCodedUITest>
|
||||
<TestProjectType>UnitTest</TestProjectType>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
|
||||
<PackageReference Include="Microsoft.Windows.Apps.Test" Version="1.0.181205002" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.1.2" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.1.2" />
|
||||
<PackageReference Include="coverlet.collector" Version="1.3.0" />
|
||||
<PackageReference Include="MUXTestInfra.MSTest" Version="0.0.4" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Appium.Net, Version=4.3.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Appium.WebDriver.4.3.1\lib\net45\Appium.Net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Castle.Core.4.3.1\lib\net45\Castle.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\MSTest.TestFramework.2.1.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\MSTest.TestFramework.2.1.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SeleniumExtras.PageObjects, Version=3.11.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DotNetSeleniumExtras.PageObjects.3.11.0\lib\net45\SeleniumExtras.PageObjects.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="WebDriver, Version=3.141.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Selenium.WebDriver.3.141.0\lib\net45\WebDriver.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="WebDriver.Support, Version=3.141.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Selenium.Support.3.141.0\lib\net45\WebDriver.Support.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Windows.Foundation.UniversalApiContract">
|
||||
<HintPath>C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Foundation.UniversalApiContract\7.0.0.0\Windows.Foundation.UniversalApiContract.winmd</HintPath>
|
||||
<HintPath>C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Foundation.UniversalApiContract\8.0.0.0\Windows.Foundation.UniversalApiContract.winmd</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Application.cs" />
|
||||
<Compile Include="UITest.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.2.1.2\build\net45\MSTest.TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.2.1.2\build\net45\MSTest.TestAdapter.props'))" />
|
||||
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.2.1.2\build\net45\MSTest.TestAdapter.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.2.1.2\build\net45\MSTest.TestAdapter.targets'))" />
|
||||
</Target>
|
||||
<Import Project="..\packages\MSTest.TestAdapter.2.1.2\build\net45\MSTest.TestAdapter.targets" Condition="Exists('..\packages\MSTest.TestAdapter.2.1.2\build\net45\MSTest.TestAdapter.targets')" />
|
||||
</Project>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Appium.WebDriver" version="4.3.1" targetFramework="net472" />
|
||||
<package id="Castle.Core" version="4.3.1" targetFramework="net472" />
|
||||
<package id="DotNetSeleniumExtras.PageObjects" version="3.11.0" targetFramework="net472" />
|
||||
<package id="MSTest.TestAdapter" version="2.1.2" targetFramework="net472" />
|
||||
<package id="MSTest.TestFramework" version="2.1.2" targetFramework="net472" />
|
||||
<package id="Newtonsoft.Json" version="12.0.1" targetFramework="net472" />
|
||||
<package id="Selenium.Support" version="3.141.0" targetFramework="net472" />
|
||||
<package id="Selenium.WebDriver" version="3.141.0" targetFramework="net472" />
|
||||
</packages>
|
Загрузка…
Ссылка в новой задаче