Skip to content

Commit f5edb01

Browse files
committed
Added web authentication page for Azure Active Directory auth flow
1 parent e744c3f commit f5edb01

File tree

2 files changed

+136
-0
lines changed

2 files changed

+136
-0
lines changed
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
namespace Legerity.Web.Authentication.Pages
2+
{
3+
using System;
4+
using Legerity.Extensions;
5+
using Legerity.Pages;
6+
using Legerity.Web.Elements.Core;
7+
using OpenQA.Selenium;
8+
using OpenQA.Selenium.Remote;
9+
10+
/// <summary>
11+
/// Defines a page object for the Azure Active Directory login page.
12+
/// </summary>
13+
public class AzureAdLoginPage : BasePage
14+
{
15+
/// <summary>
16+
/// The expected title of the Azure AD login page.
17+
/// </summary>
18+
public const string Title = "Sign in to your account";
19+
20+
/// <summary>
21+
/// Initializes a new instance of the <see cref="AzureAdLoginPage"/> class using the <see cref="AppManager.App"/> instance that verifies the page has loaded within 2 seconds.
22+
/// </summary>
23+
public AzureAdLoginPage()
24+
{
25+
}
26+
27+
/// <summary>
28+
/// Initializes a new instance of the <see cref="AzureAdLoginPage"/> class using a <see cref="RemoteWebDriver"/> instance that verifies the page has loaded within 2 seconds.
29+
/// </summary>
30+
/// <param name="app">
31+
/// The instance of the started application driver that will be used to drive the page interaction.
32+
/// </param>
33+
/// <exception cref="T:Legerity.Exceptions.DriverNotInitializedException">Thrown if AppManager.StartApp() has not been called.</exception>
34+
/// <exception cref="T:Legerity.Exceptions.PageNotShownException">Thrown if the page is not shown in 2 seconds.</exception>
35+
public AzureAdLoginPage(RemoteWebDriver app)
36+
: base(app)
37+
{
38+
}
39+
40+
/// <summary>
41+
/// Initializes a new instance of the <see cref="AzureAdLoginPage"/> class using the <see cref="AppManager.App"/> instance that verifies the page has loaded within the given timeout.
42+
/// </summary>
43+
/// <param name="traitTimeout">
44+
/// The amount of time the driver should wait when searching for the <see cref="Trait"/> if it is not immediately present.
45+
/// </param>
46+
/// <exception cref="T:Legerity.Exceptions.DriverNotInitializedException">Thrown if AppManager.StartApp() has not been called.</exception>
47+
/// <exception cref="T:Legerity.Exceptions.PageNotShownException">Thrown if the page is not shown in the given timeout.</exception>
48+
public AzureAdLoginPage(TimeSpan? traitTimeout)
49+
: base(traitTimeout)
50+
{
51+
}
52+
53+
/// <summary>
54+
/// Initializes a new instance of the <see cref="AzureAdLoginPage"/> class using a <see cref="RemoteWebDriver"/> instance that verifies the page has loaded within the given timeout.
55+
/// </summary>
56+
/// <param name="app">
57+
/// The instance of the started application driver that will be used to drive the page interaction.
58+
/// </param>
59+
/// <param name="traitTimeout">
60+
/// The amount of time the driver should wait when searching for the <see cref="Trait"/> if it is not immediately present.
61+
/// </param>
62+
/// <exception cref="T:Legerity.Exceptions.DriverNotInitializedException">Thrown if AppManager.StartApp() has not been called.</exception>
63+
/// <exception cref="T:Legerity.Exceptions.PageNotShownException">Thrown if the page is not shown in the given timeout.</exception>
64+
public AzureAdLoginPage(RemoteWebDriver app, TimeSpan? traitTimeout)
65+
: base(app, traitTimeout)
66+
{
67+
}
68+
69+
/// <summary>
70+
/// Gets the input element for providing an email address.
71+
/// </summary>
72+
public virtual TextInput EmailInput => this.App.FindWebElement(WebByExtras.InputType("email"));
73+
74+
/// <summary>
75+
/// Gets the input element for providing a password.
76+
/// </summary>
77+
public virtual TextInput PasswordInput => this.App.FindWebElement(WebByExtras.InputType("password"));
78+
79+
/// <summary>
80+
/// Gets the button element for continuing the sign-in flow through the Azure AD login UI.
81+
/// </summary>
82+
public virtual Button SignInButton => this.App.FindWebElement(By.Id("idSIButton9"));
83+
84+
/// <summary>
85+
/// Gets the optional "Use Password" button that appears when password-less authentication is enabled.
86+
/// </summary>
87+
public virtual Button UsePasswordButton => this.App.FindWebElement(By.Id("idA_PWD_SwitchToPassword"));
88+
89+
/// <summary>
90+
/// Gets a given trait of the page to verify that the page is in view.
91+
/// </summary>
92+
protected override By Trait => By.ClassName("login-paginated-page");
93+
94+
/// <summary>
95+
/// Login an Azure Active Directory user by email and password.
96+
/// </summary>
97+
/// <param name="email">The email address to authenticate with.</param>
98+
/// <param name="password">The password associated with the email address to authenticate with.</param>
99+
/// <returns>The <see cref="AzureAdLoginPage"/> instance.</returns>
100+
public AzureAdLoginPage Login(string email, string password)
101+
{
102+
(bool hasEmailInput, AzureAdLoginPage _) =
103+
this.TryWaitUntil(page => page.EmailInput.IsVisible, this.WaitTimeout);
104+
if (!hasEmailInput)
105+
{
106+
// Cannot login as email address input not shown (possibly logged in already?)
107+
return this;
108+
}
109+
110+
this.EmailInput.SetText(email);
111+
112+
// Azure AD login uses a 2-step process for email and password.
113+
this.SignInButton.Click();
114+
115+
// Check to ensure that the user is not authenticating with password-less authentication.
116+
(bool isNotPasswordLogin, AzureAdLoginPage _) =
117+
this.TryWaitUntil(page => page.UsePasswordButton.IsVisible, this.WaitTimeout);
118+
if (isNotPasswordLogin)
119+
{
120+
this.UsePasswordButton.Click();
121+
this.TryWaitUntil(page => page.PasswordInput.IsVisible, this.WaitTimeout);
122+
}
123+
124+
this.PasswordInput.SetText(password);
125+
this.SignInButton.Click();
126+
127+
return this;
128+
}
129+
}
130+
}

src/Legerity.sln

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{9064E354
6565
EndProject
6666
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Legerity.PageObjectGenerator", "..\tools\Legerity.PageObjectGenerator\Legerity.PageObjectGenerator.csproj", "{063E6264-F623-4469-BADF-95C8E93E3ACF}"
6767
EndProject
68+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Legerity.Web.Authentication", "Legerity.Web.Authentication\Legerity.Web.Authentication.csproj", "{F6CCE4EA-9C7D-4DD0-BD6B-0B5C70EE9175}"
69+
EndProject
6870
Global
6971
GlobalSection(SolutionConfigurationPlatforms) = preSolution
7072
Debug|Any CPU = Debug|Any CPU
@@ -139,6 +141,10 @@ Global
139141
{063E6264-F623-4469-BADF-95C8E93E3ACF}.Debug|Any CPU.Build.0 = Debug|Any CPU
140142
{063E6264-F623-4469-BADF-95C8E93E3ACF}.Release|Any CPU.ActiveCfg = Release|Any CPU
141143
{063E6264-F623-4469-BADF-95C8E93E3ACF}.Release|Any CPU.Build.0 = Release|Any CPU
144+
{F6CCE4EA-9C7D-4DD0-BD6B-0B5C70EE9175}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
145+
{F6CCE4EA-9C7D-4DD0-BD6B-0B5C70EE9175}.Debug|Any CPU.Build.0 = Debug|Any CPU
146+
{F6CCE4EA-9C7D-4DD0-BD6B-0B5C70EE9175}.Release|Any CPU.ActiveCfg = Release|Any CPU
147+
{F6CCE4EA-9C7D-4DD0-BD6B-0B5C70EE9175}.Release|Any CPU.Build.0 = Release|Any CPU
142148
EndGlobalSection
143149
GlobalSection(SolutionProperties) = preSolution
144150
HideSolutionNode = FALSE

0 commit comments

Comments
 (0)