Infrastructure
This commit is contained in:
Родитель
6b4e59e876
Коммит
9eef71b865
|
@ -9,6 +9,9 @@
|
|||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# ALWAYS ignore the credential configuration, so nobody checks in their API keys
|
||||
App.config
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.24720.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdfsUITestManager", "AdfsUITestManager\AdfsUITestManager.csproj", "{540AFC72-5649-4ECF-B4D4-1273CE070504}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{540AFC72-5649-4ECF-B4D4-1273CE070504}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{540AFC72-5649-4ECF-B4D4-1273CE070504}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{540AFC72-5649-4ECF-B4D4-1273CE070504}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{540AFC72-5649-4ECF-B4D4-1273CE070504}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,95 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{540AFC72-5649-4ECF-B4D4-1273CE070504}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>AdfsUITestManager</RootNamespace>
|
||||
<AssemblyName>AdfsUITestManager</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<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' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Selenium.WebDriverBackedSelenium, Version=3.11.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Selenium.WebDriverBackedSelenium.3.11.0\lib\net45\Selenium.WebDriverBackedSelenium.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="WebDriver, Version=3.11.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Selenium.WebDriver.3.11.0\lib\net45\WebDriver.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="WebDriver.Support, Version=3.11.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Selenium.Support.3.11.0\lib\net45\WebDriver.Support.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BrowserStackLogReader.cs" />
|
||||
<Compile Include="DriverFactory.cs" />
|
||||
<Compile Include="Tasks\ExternalAuthTasks.cs" />
|
||||
<Compile Include="Tasks\FormsPageTasks.cs" />
|
||||
<Compile Include="Manager.cs" />
|
||||
<Compile Include="Tasks\OptionsPageTasks.cs" />
|
||||
<Compile Include="Tasks\PaginatedFormsTasks.cs" />
|
||||
<Compile Include="Tasks\RelyingPartyTasks.cs" />
|
||||
<Compile Include="Tasks\TaskBase.cs" />
|
||||
<Compile Include="TestCases.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ScreenShotRemoteWebDriver.cs" />
|
||||
<Compile Include="TaskConfiguration.cs" />
|
||||
<Compile Include="TaskConfigurationFactory.cs" />
|
||||
<Compile Include="Tasks\IdpPageTasks.cs" />
|
||||
<Compile Include="TestContext.cs" />
|
||||
<Compile Include="TestListConfiguration.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- 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">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
|
@ -0,0 +1,163 @@
|
|||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Linq;
|
||||
|
||||
namespace AdfsUITestManager
|
||||
{
|
||||
public enum TestStatus
|
||||
{
|
||||
Passed,
|
||||
Failed
|
||||
}
|
||||
|
||||
public class MarkTestData
|
||||
{
|
||||
public string status { get; set; }
|
||||
}
|
||||
|
||||
public enum BrowserStackDataType
|
||||
{
|
||||
Build,
|
||||
Session
|
||||
}
|
||||
|
||||
class BrowserStackLogReader
|
||||
{
|
||||
public static NetworkCredential AuthCredential = new NetworkCredential( ConfigurationManager.AppSettings[ "BrowserStackUser" ], ConfigurationManager.AppSettings[ "BrowserStackKey" ] );
|
||||
|
||||
/// <summary>
|
||||
/// BrowserStack API supports build and session queries for a given user.
|
||||
/// This method retrieves all builds or sessions, and then searches for the ID of the matching session/build by name
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="url"></param>
|
||||
/// <param name="dataType"></param>
|
||||
/// <returns></returns>
|
||||
private static string GetIdFromName( string name, string url, BrowserStackDataType dataType )
|
||||
{
|
||||
WebResponse response = null;
|
||||
StreamReader reader = null;
|
||||
// BrowserStack doesn't allow hyphens in remote names, and removes them silently
|
||||
name = name.Replace( '-', ' ' );
|
||||
|
||||
try
|
||||
{
|
||||
WebRequest request = WebRequest.Create( url );
|
||||
request.Credentials = AuthCredential;
|
||||
response = request.GetResponse();
|
||||
Stream dataStream = response.GetResponseStream();
|
||||
reader = new StreamReader( dataStream );
|
||||
string responseFromServer = reader.ReadToEnd();
|
||||
string data = "{\"data\": " + responseFromServer + "}";
|
||||
var jsonData = JObject.Parse( data );
|
||||
|
||||
// Iterate through builds until you find one that matches our build name
|
||||
for ( int i = 0; i < jsonData[ "data" ].Count(); i++ )
|
||||
{
|
||||
string automationElement = "automation_session";
|
||||
if ( dataType == BrowserStackDataType.Build )
|
||||
{
|
||||
automationElement = "automation_build";
|
||||
}
|
||||
var nameRemote = ( string )jsonData[ "data" ][ i ][ automationElement ][ "name" ];
|
||||
|
||||
if ( nameRemote.Equals( name ) )
|
||||
{
|
||||
return ( string )jsonData[ "data" ][ i ][ automationElement ][ "hashed_id" ];
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
Console.WriteLine( "Error while trying to call BrowserStack." );
|
||||
Console.WriteLine( e.Message );
|
||||
Console.WriteLine( e.StackTrace );
|
||||
}
|
||||
finally
|
||||
{
|
||||
reader?.Close();
|
||||
response?.Close();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Locates the BrowserStack session ID for a given build and session name.
|
||||
/// </summary>
|
||||
/// <param name="buildName"></param>
|
||||
/// <param name="sessionName"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetSessionId(string buildName, string sessionName)
|
||||
{
|
||||
var buildId = GetIdFromName( buildName, $"https://api.browserstack.com/automate/builds.json", BrowserStackDataType.Build );
|
||||
|
||||
if ( string.IsNullOrEmpty( buildId ) )
|
||||
{
|
||||
Console.WriteLine("Error getting build ID. No matching build ID found.");
|
||||
return null;
|
||||
}
|
||||
|
||||
var sessionId = GetIdFromName( sessionName, $"https://api.browserstack.com/automate/builds/{buildId}/sessions.json", BrowserStackDataType.Session );
|
||||
if ( string.IsNullOrEmpty( sessionId ) )
|
||||
{
|
||||
Console.WriteLine( "Error getting session ID. No matching session ID found." );
|
||||
return null;
|
||||
}
|
||||
|
||||
return sessionId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Marks a test corresponding to the given session ID with the test status supplied.
|
||||
/// This method is used to mark tests as "pass" or "fail", based on what occurs in the ADFS environment.
|
||||
/// </summary>
|
||||
/// <param name="sessionId"></param>
|
||||
/// <param name="status"></param>
|
||||
public static void MarkTest( string sessionId, TestStatus status)
|
||||
{
|
||||
try
|
||||
{
|
||||
string url = $"https://api.browserstack.com/";
|
||||
var handler = new HttpClientHandler { Credentials = AuthCredential };
|
||||
HttpClient client = new HttpClient( handler );
|
||||
client.BaseAddress = new Uri( url );
|
||||
|
||||
// Create the data to PUT
|
||||
MarkTestData data = new MarkTestData();
|
||||
data.status = status.ToString();
|
||||
var output = JsonConvert.SerializeObject( data );
|
||||
|
||||
var inputMessage = new HttpRequestMessage
|
||||
{
|
||||
Content = new StringContent( output, Encoding.UTF8, "application/json" )
|
||||
};
|
||||
inputMessage.Headers.Accept.Add( new MediaTypeWithQualityHeaderValue( "application/json" ) );
|
||||
|
||||
HttpResponseMessage message = client.PutAsync( $"automate/sessions/{sessionId}.json", inputMessage.Content ).Result;
|
||||
|
||||
if ( message.IsSuccessStatusCode )
|
||||
{
|
||||
Console.WriteLine( "Test marked successfully" );
|
||||
}
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
Console.WriteLine( $"Failed to mark test {sessionId} with status {status}." );
|
||||
Console.WriteLine( e.Message );
|
||||
Console.WriteLine( e.StackTrace );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
using OpenQA.Selenium.Remote;
|
||||
using System.Configuration;
|
||||
|
||||
namespace AdfsUITestManager
|
||||
{
|
||||
using System;
|
||||
|
||||
using OpenQA.Selenium;
|
||||
|
||||
/// <summary>
|
||||
/// Class responsible for creating web drivers to be used for UI testing
|
||||
/// </summary>
|
||||
class DriverFactory
|
||||
{
|
||||
static readonly string RemoteDriverUri = ConfigurationManager.AppSettings[ "RemoteDriverUri" ];
|
||||
|
||||
public static IWebDriver GenerateDriver( DesiredCapabilities capability )
|
||||
{
|
||||
var driver = new RemoteWebDriver(
|
||||
new Uri( RemoteDriverUri ), capability
|
||||
);
|
||||
|
||||
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds( 10 );
|
||||
|
||||
return driver;
|
||||
}
|
||||
|
||||
public static void AddCommonCapabilities( DesiredCapabilities capability )
|
||||
{
|
||||
var user = ConfigurationManager.AppSettings[ "BrowserStackUser" ];
|
||||
var key = ConfigurationManager.AppSettings[ "BrowserStackKey" ];
|
||||
|
||||
var sessionName = $"AD FS {DateTime.UtcNow.ToFileTimeUtc()}";
|
||||
var buildName = $"AD FS Build {DateTime.UtcNow.ToString("yyyy-MM-dd")}";
|
||||
|
||||
capability.SetCapability( "browserstack.local", "true" );
|
||||
capability.SetCapability( "browserstack.user", user );
|
||||
capability.SetCapability( "browserstack.key", key );
|
||||
capability.SetCapability( "browserstack.debug", "true" );
|
||||
capability.SetCapability( "resolution", "1024x768" );
|
||||
capability.SetCapability( "build", buildName );
|
||||
capability.SetCapability( "name", sessionName );
|
||||
}
|
||||
|
||||
public static DesiredCapabilities GetChromeDriverCapabilities()
|
||||
{
|
||||
DesiredCapabilities capability = new DesiredCapabilities();
|
||||
capability.SetCapability( "browser", "Chrome" );
|
||||
capability.SetCapability( "browser_version", "62.0" );
|
||||
capability.SetCapability( "os", "Windows" );
|
||||
capability.SetCapability( "os_version", "10" );
|
||||
capability.SetCapability( "ignore-certificate", true );
|
||||
|
||||
AddCommonCapabilities( capability );
|
||||
|
||||
return capability;
|
||||
}
|
||||
|
||||
public static DesiredCapabilities GetFirefoxDriverCapabilities()
|
||||
{
|
||||
DesiredCapabilities capability = new DesiredCapabilities();
|
||||
capability.SetCapability( "os", "Windows" );
|
||||
capability.SetCapability( "os_version", "10" );
|
||||
capability.SetCapability( "browser", "Firefox" );
|
||||
capability.SetCapability( "browser_version", "58.0" );
|
||||
capability.SetCapability( "acceptInsecureCerts", true );
|
||||
|
||||
AddCommonCapabilities( capability );
|
||||
return capability;
|
||||
}
|
||||
|
||||
public static DesiredCapabilities GetIEDriverCapabilities()
|
||||
{
|
||||
DesiredCapabilities capability = new DesiredCapabilities();
|
||||
capability.SetCapability( "os", "Windows" );
|
||||
capability.SetCapability( "os_version", "10" );
|
||||
capability.SetCapability( "browser", "IE" );
|
||||
capability.SetCapability( "browser_version", "11.0" );
|
||||
|
||||
AddCommonCapabilities( capability );
|
||||
return capability;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using OpenQA.Selenium;
|
||||
using OpenQA.Selenium.Remote;
|
||||
namespace AdfsUITestManager
|
||||
{
|
||||
class Manager
|
||||
{
|
||||
static void Main( string[] args )
|
||||
{
|
||||
// Contract:
|
||||
// .\BrowserStackTestManager.exe
|
||||
|
||||
TestContext context = new TestContext();
|
||||
InvokeTests( context.DriversPerTestCase, context.Configuration );
|
||||
Console.WriteLine( "Done" );
|
||||
}
|
||||
|
||||
private static void InvokeTests( Dictionary<MethodInfo, List<DesiredCapabilities>> driversPerTest, TaskConfiguration config )
|
||||
{
|
||||
foreach ( var test in driversPerTest.Keys )
|
||||
{
|
||||
foreach ( var driverData in driversPerTest[ test] )
|
||||
{
|
||||
IWebDriver driver = DriverFactory.GenerateDriver( driverData );
|
||||
string sessionName = ( string )driverData.GetCapability( "name" );
|
||||
string buildName = ( string )driverData.GetCapability( "build" );
|
||||
|
||||
try
|
||||
{
|
||||
Console.WriteLine( $"Executing test: {test.Name}" );
|
||||
test.Invoke( null, new object[] { driver, config } );
|
||||
BrowserStackLogReader.MarkTest(BrowserStackLogReader.GetSessionId( buildName, sessionName ), TestStatus.Passed);
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
Console.WriteLine("Exception thrown during test execution.");
|
||||
Console.WriteLine( e.Message );
|
||||
Console.WriteLine( e.StackTrace );
|
||||
BrowserStackLogReader.MarkTest( BrowserStackLogReader.GetSessionId( buildName, sessionName ), TestStatus.Failed );
|
||||
driver.Quit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle( "BrowserStackPaginatedUI" )]
|
||||
[assembly: AssemblyDescription( "" )]
|
||||
[assembly: AssemblyConfiguration( "" )]
|
||||
[assembly: AssemblyCompany( "" )]
|
||||
[assembly: AssemblyProduct( "BrowserStackPaginatedUI" )]
|
||||
[assembly: AssemblyCopyright( "Copyright © 2018" )]
|
||||
[assembly: AssemblyTrademark( "" )]
|
||||
[assembly: AssemblyCulture( "" )]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible( false )]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid( "540afc72-5649-4ecf-b4d4-1273ce070504" )]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion( "1.0.0.0" )]
|
||||
[assembly: AssemblyFileVersion( "1.0.0.0" )]
|
|
@ -0,0 +1,25 @@
|
|||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using OpenQA.Selenium;
|
||||
using OpenQA.Selenium.Remote;
|
||||
|
||||
namespace AdfsUITestManager
|
||||
{
|
||||
public class ScreenShotRemoteWebDriver : RemoteWebDriver, ITakesScreenshot
|
||||
{
|
||||
public ScreenShotRemoteWebDriver( Uri uri, DesiredCapabilities dc )
|
||||
: base( uri, dc )
|
||||
{
|
||||
}
|
||||
|
||||
public Screenshot GetScreenshot()
|
||||
{
|
||||
Response screenshotResponse = this.Execute( DriverCommand.Screenshot, null );
|
||||
string base64 = screenshotResponse.Value.ToString();
|
||||
return new Screenshot( base64 );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,255 @@
|
|||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
using System.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AdfsUITestManager
|
||||
{
|
||||
public class TaskConfiguration : ConfigurationSection
|
||||
{
|
||||
[ConfigurationProperty( "farmData" )]
|
||||
public FarmDataElement Farm
|
||||
{
|
||||
get
|
||||
{
|
||||
return ( FarmDataElement )this[ "farmData" ];
|
||||
}
|
||||
set
|
||||
{ this[ "farmData" ] = value; }
|
||||
}
|
||||
|
||||
[ConfigurationProperty( "userData" )]
|
||||
public UserDataElement User
|
||||
{
|
||||
get
|
||||
{
|
||||
return ( UserDataElement )this[ "userData" ];
|
||||
}
|
||||
set
|
||||
{ this[ "userData" ] = value; }
|
||||
}
|
||||
|
||||
[ConfigurationProperty( "relyingPartyData" )]
|
||||
public RelyingPartyDataElement RelyingPartyData
|
||||
{
|
||||
get
|
||||
{
|
||||
return ( RelyingPartyDataElement )this[ "relyingPartyData" ];
|
||||
}
|
||||
set
|
||||
{ this[ "relyingPartyData" ] = value; }
|
||||
}
|
||||
|
||||
[ConfigurationProperty( "screenshot" )]
|
||||
public ScreenshotDataElement ScreenshotData
|
||||
{
|
||||
get
|
||||
{
|
||||
return ( ScreenshotDataElement )this[ "screenshot" ];
|
||||
}
|
||||
set
|
||||
{ this[ "screenshot" ] = value; }
|
||||
}
|
||||
|
||||
[ConfigurationProperty( "externalAuth" )]
|
||||
public ExternalAuthDataElement ExternalAuth
|
||||
{
|
||||
get
|
||||
{
|
||||
return ( ExternalAuthDataElement )this[ "externalAuth" ];
|
||||
}
|
||||
set
|
||||
{ this[ "externalAuth" ] = value; }
|
||||
}
|
||||
}
|
||||
|
||||
public class ExternalAuthDataElement : ConfigurationElement
|
||||
{
|
||||
[ConfigurationProperty( "challengeAnswers", IsRequired = true )]
|
||||
public string AnswersString
|
||||
{
|
||||
get
|
||||
{
|
||||
return ( String )this[ "challengeAnswers" ];
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> Answers
|
||||
{
|
||||
get
|
||||
{
|
||||
List<string> answers = new List<string>( AnswersString.Split( ',' ) );
|
||||
return answers;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ScreenshotDataElement : ConfigurationElement
|
||||
{
|
||||
[ConfigurationProperty( "shouldScreenshot", IsRequired = true )]
|
||||
public Boolean ShouldScreenshot
|
||||
{
|
||||
get
|
||||
{
|
||||
return ( Boolean )this[ "shouldScreenshot" ];
|
||||
}
|
||||
set
|
||||
{
|
||||
this[ "shouldScreenshot" ] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class RelyingPartyDataElement : ConfigurationElement
|
||||
{
|
||||
[ConfigurationProperty( "name", IsRequired = true )]
|
||||
public String Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return ( String )this[ "name" ];
|
||||
}
|
||||
set
|
||||
{
|
||||
this[ "name" ] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty( "wtrealm", IsRequired = true )]
|
||||
public String Wtrealm
|
||||
{
|
||||
get
|
||||
{
|
||||
return ( String )this[ "wtrealm" ];
|
||||
}
|
||||
set
|
||||
{
|
||||
this[ "wtrealm" ] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty( "wreply", IsRequired = true )]
|
||||
public String Wreply
|
||||
{
|
||||
get
|
||||
{
|
||||
return ( String )this[ "wreply" ];
|
||||
}
|
||||
set
|
||||
{
|
||||
this[ "wreply" ] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class FarmDataElement : ConfigurationElement
|
||||
{
|
||||
[ConfigurationProperty( "farmName", IsRequired = true )]
|
||||
public String FarmName
|
||||
{
|
||||
get
|
||||
{
|
||||
return ( String )this[ "farmName" ];
|
||||
}
|
||||
set
|
||||
{
|
||||
this[ "farmName" ] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class UserDataElement : ConfigurationElement
|
||||
{
|
||||
[ConfigurationProperty( "misformattedUsername", IsRequired = true )]
|
||||
public String MisformattedUsername
|
||||
{
|
||||
get
|
||||
{
|
||||
return ( String )this[ "misformattedUsername" ];
|
||||
}
|
||||
set
|
||||
{
|
||||
this[ "misformattedUsername" ] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty( "correctUsername", IsRequired = true )]
|
||||
public String CorrectUsername
|
||||
{
|
||||
get
|
||||
{
|
||||
return ( String )this[ "correctUsername" ];
|
||||
}
|
||||
set
|
||||
{
|
||||
this[ "correctUsername" ] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty( "correctPassword", IsRequired = true )]
|
||||
public String CorrectPassword
|
||||
{
|
||||
get
|
||||
{
|
||||
return ( String )this[ "correctPassword" ];
|
||||
}
|
||||
set
|
||||
{
|
||||
this[ "correctPassword" ] = value;
|
||||
}
|
||||
}
|
||||
[ConfigurationProperty( "badPassword", IsRequired = true )]
|
||||
public String BadPassword
|
||||
{
|
||||
get
|
||||
{
|
||||
return ( String )this[ "badPassword" ];
|
||||
}
|
||||
set
|
||||
{
|
||||
this[ "badPassword" ] = value;
|
||||
}
|
||||
}
|
||||
[ConfigurationProperty( "externalAuthUsername", IsRequired = true )]
|
||||
public String ExternalAuthUsername
|
||||
{
|
||||
get
|
||||
{
|
||||
return ( String )this[ "externalAuthUsername" ];
|
||||
}
|
||||
set
|
||||
{
|
||||
this[ "externalAuthUsername" ] = value;
|
||||
}
|
||||
}
|
||||
[ConfigurationProperty( "adminUsername", IsRequired = true )]
|
||||
public String AdminUsername
|
||||
{
|
||||
get
|
||||
{
|
||||
return ( String )this[ "adminUsername" ];
|
||||
}
|
||||
set
|
||||
{
|
||||
this[ "adminUsername" ] = value;
|
||||
}
|
||||
}
|
||||
[ConfigurationProperty( "badUsername", IsRequired = true )]
|
||||
public String BadUsername
|
||||
{
|
||||
get
|
||||
{
|
||||
return ( String )this[ "badUsername" ];
|
||||
}
|
||||
set
|
||||
{
|
||||
this[ "badUsername" ] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace AdfsUITestManager
|
||||
{
|
||||
class TaskConfigurationFactory
|
||||
{
|
||||
public static TaskConfiguration GetConfiguration()
|
||||
{
|
||||
TaskConfiguration config = ( TaskConfiguration ) System.Configuration.ConfigurationManager.GetSection( "taskConfigurationGroup/taskConfiguration" );
|
||||
return config;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
using OpenQA.Selenium;
|
||||
|
||||
namespace AdfsUITestManager
|
||||
{
|
||||
/// <summary>
|
||||
/// A class containing the tasks that can be performed on the External Authentication UI Page through AD FS
|
||||
/// </summary>
|
||||
class ExternalAuthTasks : TaskBase
|
||||
{
|
||||
/// <summary>
|
||||
/// A task to enter an answer to a challenge question provided by an External Auth Provider
|
||||
/// that prompts with challenge questions
|
||||
///
|
||||
/// Note: This External Auth Adapter is based on a test auth adapter used by the AD FS Product Group
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="driver">A web driver</param>
|
||||
/// <param name="config">Configuration data for this task</param>
|
||||
public static void EnterChallengeAnswers( IWebDriver driver, TaskConfiguration config )
|
||||
{
|
||||
LogAndScreenshot( driver, config );
|
||||
|
||||
foreach ( string answer in config.ExternalAuth.Answers )
|
||||
{
|
||||
IWebElement challengeField = driver.FindElement( By.Id( "challengeQuestionInput" ) );
|
||||
challengeField.SendKeys( $"{answer}" );
|
||||
challengeField.SendKeys( Keys.Return );
|
||||
LogAndScreenshot( driver, config );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
using OpenQA.Selenium;
|
||||
|
||||
namespace AdfsUITestManager
|
||||
{
|
||||
/// <summary>
|
||||
/// A class containing the tasks that can be performed on the Username/Password Page through AD FS
|
||||
/// </summary>
|
||||
class FormsPageTasks : TaskBase
|
||||
{
|
||||
// TODO: Add tasks to use 'Next' button instead of Return key
|
||||
|
||||
public static void EnterMisformattedUsername( IWebDriver driver, TaskConfiguration config )
|
||||
{
|
||||
IWebElement usernameField = driver.FindElement( By.Id( "userNameInput" ) );
|
||||
usernameField.SendKeys( $"{config.User.MisformattedUsername}" );
|
||||
usernameField.SendKeys( Keys.Return );
|
||||
|
||||
// TODO: Validate that the error message appears
|
||||
|
||||
LogAndScreenshot( driver, config );
|
||||
}
|
||||
|
||||
public static void ClearUsername( IWebDriver driver, TaskConfiguration config )
|
||||
{
|
||||
IWebElement usernameField = driver.FindElement( By.Id( "userNameInput" ) );
|
||||
usernameField.Clear();
|
||||
}
|
||||
|
||||
public static void EnterBadUsername( IWebDriver driver, TaskConfiguration config )
|
||||
{
|
||||
IWebElement usernameField = driver.FindElement( By.Id( "userNameInput" ) );
|
||||
usernameField.SendKeys( $"{config.User.BadUsername}" );
|
||||
|
||||
LogAndScreenshot( driver, config );
|
||||
|
||||
usernameField.SendKeys( Keys.Return );
|
||||
|
||||
// TODO: Validate that the error message appears
|
||||
}
|
||||
|
||||
public static void EnterCorrectUsername( IWebDriver driver, TaskConfiguration config )
|
||||
{
|
||||
IWebElement usernameField = driver.FindElement( By.Id( "userNameInput" ) );
|
||||
usernameField.SendKeys( $"{config.User.CorrectUsername}" );
|
||||
LogAndScreenshot( driver, config );
|
||||
usernameField.SendKeys( Keys.Return );
|
||||
}
|
||||
|
||||
public static void EnterCorrectUsernameAndTab( IWebDriver driver, TaskConfiguration config )
|
||||
{
|
||||
IWebElement usernameField = driver.FindElement( By.Id( "userNameInput" ) );
|
||||
usernameField.SendKeys( $"{config.User.CorrectUsername}" );
|
||||
LogAndScreenshot( driver, config );
|
||||
usernameField.SendKeys( Keys.Tab );
|
||||
}
|
||||
|
||||
public static void EnterBadPassword( IWebDriver driver, TaskConfiguration config )
|
||||
{
|
||||
LogAndScreenshot( driver, config );
|
||||
|
||||
IWebElement passwordField = driver.FindElement( By.Id( "passwordInput" ) );
|
||||
passwordField.SendKeys( $"{config.User.BadPassword}" );
|
||||
passwordField.SendKeys( Keys.Return );
|
||||
|
||||
LogAndScreenshot( driver, config );
|
||||
}
|
||||
|
||||
public static void EnterCorrectPassword( IWebDriver driver, TaskConfiguration config )
|
||||
{
|
||||
LogAndScreenshot( driver, config );
|
||||
|
||||
IWebElement passwordField = driver.FindElement( By.Id( "passwordInput" ) );
|
||||
passwordField.SendKeys( $"{config.User.CorrectPassword}" );
|
||||
passwordField.SendKeys( Keys.Return );
|
||||
LogAndScreenshot( driver, config );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
using OpenQA.Selenium;
|
||||
|
||||
namespace AdfsUITestManager
|
||||
{
|
||||
/// <summary>
|
||||
/// A class containing the tasks that can be performed on the IDP Initiated Sign On Page through AD FS
|
||||
/// </summary>
|
||||
class IdpPageTasks : TaskBase
|
||||
{
|
||||
public static void GoToIdpSignOnPage( IWebDriver driver, TaskConfiguration config )
|
||||
{
|
||||
string url = $"https://{config.Farm.FarmName}/adfs/ls/idpinitiatedsignon";
|
||||
driver.Navigate().GoToUrl( url );
|
||||
LogAndScreenshot( driver, config );
|
||||
}
|
||||
|
||||
public static void GoToIdpSignOnPageWithLoginHint( IWebDriver driver, TaskConfiguration config )
|
||||
{
|
||||
driver.Navigate().GoToUrl( $"https://{config.Farm.FarmName}/adfs/ls/idpinitiatedsignon?login_hint={config.User.CorrectUsername}" );
|
||||
LogAndScreenshot( driver, config );
|
||||
}
|
||||
|
||||
public static void ClickSignInOnIdpPage( IWebDriver driver, TaskConfiguration config )
|
||||
{
|
||||
IWebElement signInButton = driver.FindElement( By.Id( "idp_SignInButton" ) );
|
||||
signInButton.Click();
|
||||
LogAndScreenshot( driver, config );
|
||||
}
|
||||
|
||||
public static bool ValidateSignedIn( IWebDriver driver, TaskConfiguration config )
|
||||
{
|
||||
IWebElement signOutButton = driver.FindElement( By.Id( "idp_SignOutPanel" ) );
|
||||
LogAndScreenshot( driver, config );
|
||||
return signOutButton != null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
using OpenQA.Selenium;
|
||||
|
||||
namespace AdfsUITestManager
|
||||
{
|
||||
/// <summary>
|
||||
/// A class containing the tasks that can be performed on the Primary/Secondary Credential Options Page through AD FS
|
||||
/// </summary>
|
||||
class OptionsPageTasks : TaskBase
|
||||
{
|
||||
public static void SelectFormsOnOptionPage( IWebDriver driver, TaskConfiguration config )
|
||||
{
|
||||
LogAndScreenshot( driver, config );
|
||||
|
||||
IWebElement passwordOption = driver.FindElement( By.Id( "FormsAuthentication" ) );
|
||||
passwordOption.Click();
|
||||
}
|
||||
|
||||
public static void SelectCertOnOptionPage( IWebDriver driver, TaskConfiguration config )
|
||||
{
|
||||
LogAndScreenshot( driver, config );
|
||||
|
||||
IWebElement certOption = driver.FindElement( By.Id( "CertificateAuthentication" ) );
|
||||
certOption.Click();
|
||||
|
||||
LogAndScreenshot( driver, config );
|
||||
}
|
||||
|
||||
public static void SelectExternalOnOptionPage( IWebDriver driver, TaskConfiguration config )
|
||||
{
|
||||
LogAndScreenshot( driver, config );
|
||||
|
||||
IWebElement externalOption = driver.FindElement( By.Id( "ExternalAuth" ) );
|
||||
externalOption.Click();
|
||||
|
||||
LogAndScreenshot( driver, config );
|
||||
}
|
||||
|
||||
public static void SignInWithOtherOptions( IWebDriver driver, TaskConfiguration config )
|
||||
{
|
||||
LogAndScreenshot( driver, config );
|
||||
|
||||
IWebElement otherOption = driver.FindElement( By.Id( "otherOptions" ) );
|
||||
otherOption.Click();
|
||||
|
||||
LogAndScreenshot( driver, config );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
using OpenQA.Selenium;
|
||||
|
||||
namespace AdfsUITestManager
|
||||
{
|
||||
/// <summary>
|
||||
/// A class containing the tasks that can be performed on the Paginated Login Page through AD FS
|
||||
/// </summary>
|
||||
class PaginatedFormsTasks : TaskBase
|
||||
{
|
||||
public static void PasswordPageBackNavigate( IWebDriver driver, TaskConfiguration config )
|
||||
{
|
||||
LogAndScreenshot( driver, config );
|
||||
|
||||
IWebElement backButton = driver.FindElement( By.Id( "backButton" ) );
|
||||
backButton.Click();
|
||||
|
||||
LogAndScreenshot( driver, config );
|
||||
}
|
||||
|
||||
public static void OptionsPageBackNavigate( IWebDriver driver, TaskConfiguration config )
|
||||
{
|
||||
LogAndScreenshot( driver, config );
|
||||
|
||||
IWebElement backButton = driver.FindElement( By.Id( "optionsBackButton" ) );
|
||||
backButton.Click();
|
||||
|
||||
LogAndScreenshot( driver, config );
|
||||
}
|
||||
|
||||
public static void UsernamePageForwardNavigate( IWebDriver driver, TaskConfiguration config )
|
||||
{
|
||||
LogAndScreenshot( driver, config );
|
||||
|
||||
IWebElement nextButton = driver.FindElement( By.Id( "nextButton" ) );
|
||||
nextButton.Click();
|
||||
|
||||
LogAndScreenshot( driver, config );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using OpenQA.Selenium;
|
||||
|
||||
namespace AdfsUITestManager.Tasks
|
||||
{
|
||||
/// <summary>
|
||||
/// A class containing the tasks that can be performed when requesting a Relying Party through AD FS
|
||||
/// </summary>
|
||||
class RelyingPartyTasks : TaskBase
|
||||
{
|
||||
public static void GoToRpSignIn( IWebDriver driver, TaskConfiguration config )
|
||||
{
|
||||
string url = $"https://{config.Farm.FarmName}/adfs/ls/?wa=wsignin1.0&wtrealm={config.RelyingPartyData.Wtrealm}&wreply={config.RelyingPartyData.Wreply}";
|
||||
driver.Navigate().GoToUrl( url );
|
||||
LogAndScreenshot( driver, config );
|
||||
}
|
||||
|
||||
public static bool ValidateRpIsSignedIn( IWebDriver driver, TaskConfiguration config )
|
||||
{
|
||||
LogAndScreenshot( driver, config );
|
||||
return string.Compare( driver.Url, config.RelyingPartyData.Wreply, StringComparison.InvariantCultureIgnoreCase ) == 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using OpenQA.Selenium;
|
||||
|
||||
namespace AdfsUITestManager
|
||||
{
|
||||
class TaskBase
|
||||
{
|
||||
public static void LogAndScreenshot( IWebDriver driver, TaskConfiguration config )
|
||||
{
|
||||
Console.WriteLine( $"Current Page Title: {driver.Title}" );
|
||||
if ( config.ScreenshotData.ShouldScreenshot )
|
||||
{
|
||||
Screenshot ss = ( ( ITakesScreenshot )driver ).GetScreenshot();
|
||||
ss.SaveAsFile( $"{ DateTime.Now:yyyy - MM - dd_hh - mm - ss - fff}.png", ScreenshotImageFormat.Png );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,237 @@
|
|||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
using OpenQA.Selenium;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace AdfsUITestManager
|
||||
{
|
||||
using AdfsUITestManager.Tasks;
|
||||
|
||||
public class TestCases
|
||||
{
|
||||
#region IDP Initiated Sign On Tests
|
||||
/// <summary>
|
||||
/// ENVIRONMENT REQUIREMENTS:
|
||||
/// 1. Paginated UI feature enabled
|
||||
/// 2. Multiple auth options available
|
||||
/// </summary>
|
||||
/// <param name="driver"></param>
|
||||
static void BasicIdpSignOn_WithOptions_Password( IWebDriver driver, TaskConfiguration configuration )
|
||||
{
|
||||
// Perform UI Operations
|
||||
IdpPageTasks.GoToIdpSignOnPage( driver, configuration );
|
||||
IdpPageTasks.ClickSignInOnIdpPage( driver, configuration );
|
||||
FormsPageTasks.EnterMisformattedUsername( driver, configuration );
|
||||
FormsPageTasks.ClearUsername( driver, configuration );
|
||||
FormsPageTasks.EnterCorrectUsername( driver, configuration );
|
||||
OptionsPageTasks.SelectFormsOnOptionPage( driver, configuration );
|
||||
FormsPageTasks.EnterBadPassword( driver, configuration );
|
||||
OptionsPageTasks.SelectFormsOnOptionPage( driver, configuration );
|
||||
FormsPageTasks.EnterCorrectPassword( driver, configuration );
|
||||
|
||||
// Perform test validation
|
||||
var success = IdpPageTasks.ValidateSignedIn( driver, configuration );
|
||||
Debug.Assert( success );
|
||||
|
||||
// Clean up
|
||||
driver.Quit();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ENVIRONMENT REQUIREMENTS:
|
||||
/// 1. Paginated UI feature enabled
|
||||
/// 2. Multiple auth options available (including certificate)
|
||||
/// </summary>
|
||||
/// <param name="driver"></param>
|
||||
static void BasicIdpSignOn_WithOptions_CertThenForms( IWebDriver driver, TaskConfiguration configuration )
|
||||
{
|
||||
// Perform UI Operations
|
||||
IdpPageTasks.GoToIdpSignOnPage( driver, configuration );
|
||||
IdpPageTasks.ClickSignInOnIdpPage( driver, configuration );
|
||||
FormsPageTasks.EnterMisformattedUsername( driver, configuration );
|
||||
FormsPageTasks.EnterCorrectUsername( driver, configuration );
|
||||
OptionsPageTasks.SelectCertOnOptionPage( driver, configuration );
|
||||
OptionsPageTasks.SignInWithOtherOptions( driver, configuration );
|
||||
OptionsPageTasks.SelectFormsOnOptionPage( driver, configuration );
|
||||
FormsPageTasks.EnterCorrectPassword( driver, configuration );
|
||||
|
||||
// Perform test validation
|
||||
var success = IdpPageTasks.ValidateSignedIn( driver, configuration );
|
||||
Debug.Assert( success );
|
||||
|
||||
// Cleanup
|
||||
driver.Quit();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ENVIRONMENT REQUIREMENTS:
|
||||
/// 1. Paginated UI feature enabled
|
||||
/// 2. Multiple auth options available (including external)
|
||||
/// 3. User configured for external auth
|
||||
/// </summary>
|
||||
/// <param name="driver"></param>
|
||||
static void BasicIdpSignOn_WithOptions_External( IWebDriver driver, TaskConfiguration configuration )
|
||||
{
|
||||
// Perform UI Operations
|
||||
IdpPageTasks.GoToIdpSignOnPage( driver, configuration );
|
||||
IdpPageTasks.ClickSignInOnIdpPage( driver, configuration );
|
||||
FormsPageTasks.EnterCorrectUsername( driver, configuration );
|
||||
OptionsPageTasks.SelectExternalOnOptionPage( driver, configuration );
|
||||
ExternalAuthTasks.EnterChallengeAnswers( driver, configuration );
|
||||
|
||||
// Perform test validation
|
||||
var success = IdpPageTasks.ValidateSignedIn( driver, configuration );
|
||||
Debug.Assert( success );
|
||||
|
||||
// Cleanup
|
||||
driver.Quit();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ENVIRONMENT REQUIREMENTS:
|
||||
/// 1. Paginated UI feature enabled
|
||||
/// 2. Multiple auth options available (including external)
|
||||
/// 3. User configured for external auth
|
||||
/// </summary>
|
||||
/// <param name="driver"></param>
|
||||
static void HintIdpSignOn_WithOptions_External( IWebDriver driver, TaskConfiguration configuration )
|
||||
{
|
||||
// Perform UI Operations
|
||||
IdpPageTasks.GoToIdpSignOnPageWithLoginHint( driver, configuration );
|
||||
IdpPageTasks.ClickSignInOnIdpPage( driver, configuration );
|
||||
OptionsPageTasks.SelectExternalOnOptionPage( driver, configuration );
|
||||
ExternalAuthTasks.EnterChallengeAnswers( driver, configuration );
|
||||
|
||||
// Perform test validation
|
||||
var success = IdpPageTasks.ValidateSignedIn( driver, configuration );
|
||||
Debug.Assert( success );
|
||||
|
||||
// Cleanup
|
||||
driver.Quit();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ENVIRONMENT REQUIREMENTS:
|
||||
/// 1. Paginated UI feature enabled
|
||||
/// 2. Multiple auth options available (including external)
|
||||
/// </summary>
|
||||
/// <param name="driver"></param>
|
||||
static void HintIdpSignOn_WithOptions_Password_ChangeUser( IWebDriver driver, TaskConfiguration configuration )
|
||||
{
|
||||
// Perform UI Operations
|
||||
IdpPageTasks.GoToIdpSignOnPageWithLoginHint( driver, configuration );
|
||||
IdpPageTasks.ClickSignInOnIdpPage( driver, configuration );
|
||||
PaginatedFormsTasks.OptionsPageBackNavigate( driver, configuration );
|
||||
FormsPageTasks.ClearUsername( driver, configuration );
|
||||
FormsPageTasks.EnterCorrectUsername( driver, configuration );
|
||||
OptionsPageTasks.SelectFormsOnOptionPage( driver, configuration );
|
||||
FormsPageTasks.EnterCorrectPassword( driver, configuration );
|
||||
|
||||
// Perform test validation
|
||||
var success = IdpPageTasks.ValidateSignedIn( driver, configuration );
|
||||
Debug.Assert( success );
|
||||
|
||||
// Cleanup
|
||||
driver.Quit();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ENVIRONMENT REQUIREMENTS:
|
||||
/// 1. Paginated UI feature enabled
|
||||
/// 2. Only forms auth options available
|
||||
/// </summary>
|
||||
/// <param name="driver"></param>
|
||||
static void BasicIdpSignOn_NoOptions_Password( IWebDriver driver, TaskConfiguration configuration )
|
||||
{
|
||||
// Perform UI Operations
|
||||
IdpPageTasks.GoToIdpSignOnPage( driver, configuration );
|
||||
IdpPageTasks.ClickSignInOnIdpPage( driver, configuration );
|
||||
FormsPageTasks.EnterMisformattedUsername( driver, configuration );
|
||||
FormsPageTasks.EnterCorrectUsername( driver, configuration );
|
||||
PaginatedFormsTasks.PasswordPageBackNavigate( driver, configuration );
|
||||
PaginatedFormsTasks.UsernamePageForwardNavigate( driver, configuration );
|
||||
FormsPageTasks.EnterCorrectPassword( driver, configuration );
|
||||
|
||||
// Perform test validation
|
||||
var success = IdpPageTasks.ValidateSignedIn( driver, configuration );
|
||||
Debug.Assert( success );
|
||||
|
||||
// Cleanup
|
||||
driver.Quit();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ENVIRONMENT REQUIREMENTS:
|
||||
/// 1. Paginated UI feature disabled
|
||||
/// </summary>
|
||||
/// <param name="driver"></param>
|
||||
static void BasicIdpSignOn_Password_Legacy( IWebDriver driver, TaskConfiguration configuration )
|
||||
{
|
||||
// Perform UI Operations
|
||||
IdpPageTasks.GoToIdpSignOnPage( driver, configuration );
|
||||
IdpPageTasks.ClickSignInOnIdpPage( driver, configuration );
|
||||
FormsPageTasks.EnterCorrectUsernameAndTab( driver, configuration );
|
||||
FormsPageTasks.EnterCorrectPassword( driver, configuration );
|
||||
|
||||
// Perform test validation
|
||||
var success = IdpPageTasks.ValidateSignedIn( driver, configuration );
|
||||
Debug.Assert(success);
|
||||
|
||||
// Clean up
|
||||
driver.Quit();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ENVIRONMENT REQUIREMENTS:
|
||||
/// 1. Paginated UI feature disabled
|
||||
/// </summary>
|
||||
/// <param name="driver"></param>
|
||||
static void BasicIdpSignOn_Password_Failure_Legacy( IWebDriver driver, TaskConfiguration configuration )
|
||||
{
|
||||
// Perform UI Operations
|
||||
IdpPageTasks.GoToIdpSignOnPage( driver, configuration );
|
||||
IdpPageTasks.ClickSignInOnIdpPage( driver, configuration );
|
||||
FormsPageTasks.EnterCorrectUsername( driver, configuration );
|
||||
FormsPageTasks.EnterBadPassword( driver, configuration );
|
||||
|
||||
// Perform test validation
|
||||
var success = IdpPageTasks.ValidateSignedIn( driver, configuration );
|
||||
Debug.Assert( success );
|
||||
|
||||
// Cleanup
|
||||
driver.Quit();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Basic RP Sign On Tests
|
||||
/// <summary>
|
||||
/// ENVIRONMENT REQUIREMENTS:
|
||||
/// 1. Paginated UI feature enabled
|
||||
/// 2. Multiple auth options available
|
||||
/// 3. Relying party exists, and user has access to it
|
||||
/// </summary>
|
||||
/// <param name="driver"></param>
|
||||
static void BasicRpSignOn_WithOptions_Password( IWebDriver driver, TaskConfiguration configuration )
|
||||
{
|
||||
// Perform UI Operations
|
||||
RelyingPartyTasks.GoToRpSignIn( driver, configuration );
|
||||
FormsPageTasks.EnterCorrectUsername( driver, configuration );
|
||||
OptionsPageTasks.SelectFormsOnOptionPage( driver, configuration );
|
||||
FormsPageTasks.EnterBadPassword( driver, configuration );
|
||||
OptionsPageTasks.SelectFormsOnOptionPage( driver, configuration );
|
||||
FormsPageTasks.EnterCorrectPassword( driver, configuration );
|
||||
|
||||
// Perform test validation
|
||||
var success = RelyingPartyTasks.ValidateRpIsSignedIn( driver, configuration );
|
||||
Debug.Assert( success );
|
||||
|
||||
// Clean up
|
||||
driver.Quit();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using OpenQA.Selenium.Remote;
|
||||
|
||||
namespace AdfsUITestManager
|
||||
{
|
||||
using System;
|
||||
|
||||
class TestContext
|
||||
{
|
||||
public List<MethodInfo> TestCases;
|
||||
//public List<IWebDriver> BrowserDrivers;
|
||||
public TaskConfiguration Configuration;
|
||||
public Dictionary<MethodInfo, List<DesiredCapabilities>> DriversPerTestCase;
|
||||
|
||||
public TestContext()
|
||||
{
|
||||
TestListConfiguration testListConfig = ( TestListConfiguration )System.Configuration.ConfigurationManager.GetSection( "testListConfigurationGroup/testListConfiguration" );
|
||||
List<string> testCases = new List<string>( testListConfig.TestData.TestIds );
|
||||
this.TestCases = this.TestCases = ParseAndVerifyTestIds( testCases );
|
||||
|
||||
this.Configuration = TaskConfigurationFactory.GetConfiguration();
|
||||
|
||||
this.DriversPerTestCase = new Dictionary<MethodInfo, List<DesiredCapabilities>>();
|
||||
foreach ( var testcase in this.TestCases )
|
||||
{
|
||||
this.DriversPerTestCase[testcase] = new List<DesiredCapabilities> { DriverFactory.GetChromeDriverCapabilities() };
|
||||
}
|
||||
}
|
||||
|
||||
private List<MethodInfo> ParseAndVerifyTestIds( List<string> testIdsRaw )
|
||||
{
|
||||
if ( testIdsRaw.Count == 0 )
|
||||
{
|
||||
throw new ArgumentNullException( $"Cannot find any test names in string {testIdsRaw}. Please check the string, and ensure that test names are comma-separated." );
|
||||
}
|
||||
|
||||
List<MethodInfo> methods = new List<MethodInfo>();
|
||||
Type type = typeof( TestCases );
|
||||
|
||||
foreach ( var testLine in testIdsRaw )
|
||||
{
|
||||
if ( string.IsNullOrEmpty( testLine ) )
|
||||
{
|
||||
// Skip blank lines
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle the case where tests are comma-separated
|
||||
List<string> testIds = new List<string>( testLine.Split( ',' ) );
|
||||
foreach ( var test in testIds )
|
||||
{
|
||||
MethodInfo methodInfo = type.GetMethod( test, BindingFlags.Static | BindingFlags.NonPublic );
|
||||
if ( methodInfo == null )
|
||||
{
|
||||
throw new ArgumentNullException( $"Cannot find test name {test}. Please check BrowserStackTestManager.TestCases.cs to ensure your test case exists. Note: names are case-sensitive." );
|
||||
}
|
||||
|
||||
methods.Add( methodInfo );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return methods;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
|
||||
namespace AdfsUITestManager
|
||||
{
|
||||
class TestListConfiguration : ConfigurationSection
|
||||
{
|
||||
[ConfigurationProperty( "testData" )]
|
||||
public TestDataElement TestData
|
||||
{
|
||||
get
|
||||
{
|
||||
return ( TestDataElement )this[ "testData" ];
|
||||
}
|
||||
set
|
||||
{ this[ "testData" ] = value; }
|
||||
}
|
||||
|
||||
public class TestDataElement : ConfigurationElement
|
||||
{
|
||||
[ConfigurationProperty( "testIds", IsRequired = true )]
|
||||
public string TestIdsString
|
||||
{
|
||||
get
|
||||
{
|
||||
return ( String )this[ "testIds" ];
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> TestIds
|
||||
{
|
||||
get
|
||||
{
|
||||
List<string> answers = new List<string>( TestIdsString.Split( ',' ) );
|
||||
return answers;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="11.0.2" targetFramework="net452" />
|
||||
<package id="Selenium.Support" version="3.11.0" targetFramework="net452" />
|
||||
<package id="Selenium.WebDriver" version="3.11.0" targetFramework="net452" />
|
||||
<package id="Selenium.WebDriverBackedSelenium" version="3.11.0" targetFramework="net452" />
|
||||
</packages>
|
132
README.md
132
README.md
|
@ -1,5 +1,133 @@
|
|||
# AD FS Automated User Interface Testing
|
||||
|
||||
# Contributing
|
||||
## Overview
|
||||
|
||||
This project provides a set of automated UI tests that can be performed to validate the user interface of an AD FS deployment.
|
||||
Note that in order to execute these tests, you must have either your own Selenium infrastructure, or a subscription to a remote Selenium infrastructure.
|
||||
This project is set up to support BrowserStack as the remote Selenium infrastructure. You can use a free BrowserStack subscription for 100 hours of testing, after which you will need a paid subscription.
|
||||
For more details, see [BrowserStack](https://www.browserstack.com)
|
||||
|
||||
|
||||
## Requirements
|
||||
|
||||
1. Visual Studio
|
||||
|
||||
2. BrowserStack subscription, free trial, or custom Selenium infrastructure
|
||||
|
||||
3. Internet access from your AD FS Domain Controller
|
||||
|
||||
|
||||
## Building the Project
|
||||
|
||||
1. Open the `AdfsUITestManager.sln` solution in Visual Studio
|
||||
|
||||
2. In the project directory containing `AdfsUITestManager.csproj`, add an application configuration (`App.config`) file. Your `App.config` file should contain the following:
|
||||
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<sectionGroup name="taskConfigurationGroup">
|
||||
<section
|
||||
name="taskConfiguration"
|
||||
type="AdfsUITestManager.TaskConfiguration, AdfsUITestManager"
|
||||
allowLocation="true"
|
||||
allowDefinition="Everywhere" />
|
||||
</sectionGroup>
|
||||
<sectionGroup name="testListConfigurationGroup">
|
||||
<section
|
||||
name="testListConfiguration"
|
||||
type="AdfsUITestManager.TestListConfiguration, AdfsUITestManager"
|
||||
allowLocation="true"
|
||||
allowDefinition="Everywhere" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
|
||||
</startup>
|
||||
<appSettings>
|
||||
<add key="RemoteDriverUri" value="http://hub-cloud.browserstack.com/wd/hub/"/>
|
||||
<add key="BrowserStackUser" value=<ENTER BROWSERSTACK USERNAME>/>
|
||||
<add key="BrowserStackKey" value=<ENTER BROWSERTACK API KEY>/>
|
||||
</appSettings>
|
||||
<!-- Task Configuration -->
|
||||
<taskConfigurationGroup>
|
||||
<taskConfiguration>
|
||||
<farmData farmName=<ENTER FARMNAME>/>
|
||||
<userData correctUsername=<ENTER CORRECT USERNAME>
|
||||
correctPassword=<ENTER CORRECT PASSWORD>
|
||||
badPassword="badpassword"
|
||||
externalAuthUsername=<ENTER A USERNAME REGISTERED FOR EXTERNAL AUTH>
|
||||
adminUsername=<ENTER ADMIN USERNAME>
|
||||
badUsername="badUser@farm.com"
|
||||
misformattedUsername="wronguser"
|
||||
/>
|
||||
<relyingPartyData name=<ENTER RP NAME>
|
||||
wtrealm=<ENTER WTREALM>
|
||||
wreply=<ENTER WREPLY>
|
||||
/>
|
||||
<screenshot shouldScreenshot="true"/>
|
||||
<externalAuth challengeAnswers=<ENTER ANSWERS, COMMA SEPARATED> />
|
||||
</taskConfiguration>
|
||||
</taskConfigurationGroup>
|
||||
<!-- Test List Configuration -->
|
||||
<testListConfigurationGroup>
|
||||
<testListConfiguration>
|
||||
<testData testIds="BasicRpSignOn_WithOptions_Password" />
|
||||
</testListConfiguration>
|
||||
</testListConfigurationGroup>
|
||||
</configuration>
|
||||
|
||||
You can locate the BrowserStack settings [here](https://www.browserstack.com/automate/c-sharp)
|
||||
|
||||
3. Update the list of test IDs under the `<testListConfiguration>` element to include the comma-separated list of tests you wish to run against your environment.
|
||||
The list of supported test cases is in `TestCases.cs`. If you wish to add more tests, please add them under `TestCases.cs`.
|
||||
|
||||
4. Build the project using Visual Studio
|
||||
|
||||
|
||||
## Setting Up Your Environment
|
||||
|
||||
To execute the UI tests against your own AD FS environment, you must:
|
||||
|
||||
**Deploy BrowserStack Test Agent**
|
||||
|
||||
1. Install the [BrowserStack local testing agent](https://www.browserstack.com/browserstack-local/BrowserStackLocal-win32.zip) on your AD FS Domain Controller.
|
||||
For more details on BrowserStack local testing, see [here](https://www.browserstack.com/local-testing)
|
||||
|
||||
2. Determine your BrowserStack Automate Access Key, under ["Settings" > "Automate"](https://www.browserstack.com/accounts/settings)
|
||||
|
||||
3. Execute the BrowerStackLocal agent by running the following in a command prompt on your AD FS Domain Controller:
|
||||
`BrowserStackLocal.exe --key <key>`
|
||||
|
||||
|
||||
## Running the Tests
|
||||
|
||||
1. Decide what test cases you want to run. Note that different test cases have different environment requirements. You should only run the tests that match your environment.
|
||||
All test cases, along with the environment requirements, are listed in `TestCases.cs`.
|
||||
|
||||
2. Update the list of test IDs under the `<testListConfiguration>` element to include the comma-separated list of tests you wish to run against your environment.
|
||||
|
||||
3. Execute the test manager by running:
|
||||
`.\AdfsUITestManager.exe`
|
||||
|
||||
## Validating the Results
|
||||
|
||||
You can find the BrowserStack results [here](https://www.browserstack.com/automate). These results will contain screenshots for all steps, along with a video you can review.
|
||||
Each test case validates that the user scenario works correctly, but it does not validate the "look and feel" of any customizations, branding, etc. you have applied.
|
||||
To ensure that the pages look and operate as you expect, we encourage you to manually examine the screenshots and video of the test runs.
|
||||
|
||||
## Submitting AD FS UI Bugs
|
||||
|
||||
If you find issues with the base AD FS User Interface, please open an [Issue](https://github.com/Microsoft/adfsUITests/issues) against this project. Please include the following information:
|
||||
|
||||
1. Your AD FS Build Number and Behavior Level (major and minor, if applicable)
|
||||
|
||||
2. A detailed description of the problem you see
|
||||
|
||||
3. Screenshots of the issue you see
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
This project welcomes contributions and suggestions. Most contributions require you to agree to a
|
||||
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
|
||||
|
@ -11,4 +139,4 @@ provided by the bot. You will only need to do this once across all repos using o
|
|||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
||||
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
|
||||
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
Загрузка…
Ссылка в новой задаче