-
Notifications
You must be signed in to change notification settings - Fork 1k
OIDC Ui Test Automation #791
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
04f5a6a
added Ui test for multiple API sample
JoshLozensky e576909
updating for help with debugging
JoshLozensky 03e71ce
making draft PR
JoshLozensky f84fb66
adding temporary appsettings.json fix
JoshLozensky 6cfd554
small constants update
JoshLozensky fdac0a3
Created B2C UI test
JoshLozensky b836757
sort usings
JoshLozensky 1bccda8
adding helpers
JoshLozensky 9e15088
rearranging
JoshLozensky 2e29cf0
removing project going in a different branch
JoshLozensky 02d5dc0
Added building sample to test
JoshLozensky 025947b
Adding notes
JoshLozensky 3f14ac1
remove unneeded edits
JoshLozensky ea5f258
Update UiTests/Common/TestConstants.cs
JoshLozensky 880cf53
enabled nullables
JoshLozensky d448a7b
Merge branch 'lozenksy/AddingUiTests' of https://github.com/Azure-Sam…
JoshLozensky 4a02242
Update UiTests/AnyOrgOrPersonalUiTest/AnyOrgOrPersonalTest.cs
JoshLozensky 4d48da0
Update UiTests/AnyOrgOrPersonalUiTest/AnyOrgOrPersonalTest.cs
JoshLozensky e8a5398
Update UiTests/Common/UiTestHelpers.cs
JoshLozensky 7b7e203
Update UiTests/Common/UiTestHelpers.cs
JoshLozensky 6e369fc
Addressing PR comments
JoshLozensky 167b79e
addressed PR feedback
JoshLozensky 0913e36
Update UiTests/Common/UiTestHelpers.cs
JoshLozensky 1971a1a
Update UiTests/Common/UiTestHelpers.cs
JoshLozensky a41e865
Update UiTests/Common/UiTestHelpers.cs
JoshLozensky e27c8bb
Update UiTests/Common/UiTestHelpers.cs
JoshLozensky 89854c4
added docstring
JoshLozensky 61f33b1
Merge branch 'lozenksy/AddingUiTests' of https://github.com/Azure-Sam…
JoshLozensky File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,4 +20,4 @@ | |
}, | ||
"AllowedHosts": "*", | ||
"GraphApiUrl": "https://graph.microsoft.com" | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
// 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.Versioning; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Common; | ||
using Microsoft.Identity.Lab.Api; | ||
using Microsoft.Playwright; | ||
using Xunit; | ||
using Xunit.Abstractions; | ||
using Process = System.Diagnostics.Process; | ||
using TC = Common.TestConstants; | ||
|
||
namespace MultipleApiUiTest | ||
{ | ||
public class AnyOrgOrPersonalTest : IClassFixture<InstallPlaywrightBrowserFixture> | ||
{ | ||
private const string SignOutPageUriPath = @"/MicrosoftIdentity/Account/SignedOut"; | ||
private const uint ClientPort = 44321; | ||
private const string TraceFileClassName = "OpenIDConnect"; | ||
private const uint NumProcessRetries = 3; | ||
private const string SampleSlnFileName = "1-3-AnyOrgOrPersonal.sln"; | ||
private readonly LocatorAssertionsToBeVisibleOptions _assertVisibleOptions = new() { Timeout = 25000 }; | ||
private readonly string _sampleAppPath = "1-WebApp-OIDC" + Path.DirectorySeparatorChar + "1-3-AnyOrgOrPersonal" + Path.DirectorySeparatorChar.ToString(); | ||
private readonly string _testAppsettingsPath = "UiTests" + Path.DirectorySeparatorChar + "AnyOrgOrPersonalUiTest" + Path.DirectorySeparatorChar.ToString() + TC.AppSetttingsDotJson; | ||
private readonly string _testAssemblyLocation = typeof(AnyOrgOrPersonalTest).Assembly.Location; | ||
private readonly ITestOutputHelper _output; | ||
|
||
public AnyOrgOrPersonalTest(ITestOutputHelper output) | ||
{ | ||
_output = output; | ||
} | ||
|
||
[Fact] | ||
[SupportedOSPlatform("windows")] | ||
public async Task ChallengeUser_MicrosoftIdFlow_LocalApp_ValidEmailPasswordCreds_LoginLogout() | ||
{ | ||
// Setup web app and api environmental variables. | ||
var clientEnvVars = new Dictionary<string, string> | ||
{ | ||
{"ASPNETCORE_ENVIRONMENT", "Development"}, | ||
{TC.KestrelEndpointEnvVar, TC.HttpsStarColon + ClientPort} | ||
}; | ||
|
||
Dictionary<string, Process>? processes = null; | ||
|
||
// Arrange Playwright setup, to see the browser UI set Headless = false. | ||
const string TraceFileName = TraceFileClassName + "_LoginLogout"; | ||
using IPlaywright playwright = await Playwright.CreateAsync(); | ||
IBrowser browser = await playwright.Chromium.LaunchAsync(new() { Headless = false }); | ||
IBrowserContext context = await browser.NewContextAsync(new BrowserNewContextOptions { IgnoreHTTPSErrors = true }); | ||
await context.Tracing.StartAsync(new() { Screenshots = true, Snapshots = true, Sources = true }); | ||
IPage page = await context.NewPageAsync(); | ||
string uriWithPort = TC.LocalhostUrl + ClientPort; | ||
|
||
try | ||
{ | ||
// Build the sample app with correct appsettings file. | ||
UiTestHelpers.BuildSampleWithTestAppsettings(_testAssemblyLocation, _sampleAppPath, _testAppsettingsPath, SampleSlnFileName); | ||
|
||
// Start the web app and api processes. | ||
// The delay before starting client prevents transient devbox issue where the client fails to load the first time after rebuilding | ||
var clientProcessOptions = new ProcessStartOptions(_testAssemblyLocation, _sampleAppPath, TC.s_oidcWebAppExe, clientEnvVars); | ||
|
||
bool areProcessesRunning = UiTestHelpers.StartAndVerifyProcessesAreRunning([clientProcessOptions], out processes, NumProcessRetries); | ||
|
||
if (!areProcessesRunning) | ||
{ | ||
_output.WriteLine($"Process not started after {NumProcessRetries} attempts."); | ||
StringBuilder runningProcesses = new StringBuilder(); | ||
foreach (var process in processes) | ||
{ | ||
#pragma warning disable CA1305 // Specify IFormatProvider | ||
runningProcesses.AppendLine($"Is {process.Key} running: {UiTestHelpers.ProcessIsAlive(process.Value)}"); | ||
#pragma warning restore CA1305 // Specify IFormatProvider | ||
} | ||
Assert.Fail(TC.WebAppCrashedString + " " + runningProcesses.ToString()); | ||
} | ||
|
||
LabResponse labResponse = await LabUserHelper.GetSpecificUserAsync(TC.OIDCUser); | ||
|
||
// Initial sign in | ||
_output.WriteLine("Starting web app sign-in flow."); | ||
string email = labResponse.User.Upn; | ||
await UiTestHelpers.NavigateToWebApp(uriWithPort, page); | ||
await UiTestHelpers.EnterEmailAsync(page, email, _output); | ||
await UiTestHelpers.EnterPasswordAsync(page, labResponse.User.GetOrFetchPassword(), _output); | ||
await Assertions.Expect(page.GetByText("Integrating Azure AD V2")).ToBeVisibleAsync(_assertVisibleOptions); | ||
await Assertions.Expect(page.GetByText(email)).ToBeVisibleAsync(_assertVisibleOptions); | ||
_output.WriteLine("Web app sign-in flow successful."); | ||
|
||
// Sign out | ||
_output.WriteLine("Starting web app sign-out flow."); | ||
await page.GetByRole(AriaRole.Link, new() { Name = "Sign out" }).ClickAsync(); | ||
await UiTestHelpers.PerformSignOut_MicrosoftIdFlow(page, email, TC.LocalhostUrl + ClientPort + SignOutPageUriPath, _output); | ||
_output.WriteLine("Web app sign out successful."); | ||
} | ||
catch (Exception ex) | ||
{ | ||
// Adding guid in case of multiple test runs. This will allow screenshots to be matched to their appropriate test runs. | ||
var guid = Guid.NewGuid().ToString(); | ||
try | ||
{ | ||
if (page != null) | ||
{ | ||
await page.ScreenshotAsync(new PageScreenshotOptions() { Path = $"ChallengeUser_MicrosoftIdFlow_LocalApp_ValidEmailPasswordCreds_TodoAppFunctionsCorrectlyScreenshotFail{guid}.png", FullPage = true }); | ||
} | ||
} | ||
catch | ||
{ | ||
_output.WriteLine("No Screenshot."); | ||
} | ||
|
||
string runningProcesses = UiTestHelpers.GetRunningProcessAsString(processes); | ||
Assert.Fail($"the UI automation failed: {ex} output: {ex.Message}.\n{runningProcesses}\nTest run: {guid}"); | ||
} | ||
finally | ||
{ | ||
// Make sure all processes and their children are stopped. | ||
UiTestHelpers.EndProcesses(processes); | ||
|
||
// Stop tracing and export it into a zip archive. | ||
string path = UiTestHelpers.GetTracePath(_testAssemblyLocation, TraceFileName); | ||
await context.Tracing.StopAsync(new() { Path = path }); | ||
_output.WriteLine($"Trace data for {TraceFileName} recorded to {path}."); | ||
|
||
// Close the browser and stop Playwright. | ||
await browser.CloseAsync(); | ||
playwright.Dispose(); | ||
} | ||
} | ||
|
||
} | ||
} |
31 changes: 31 additions & 0 deletions
31
UiTests/AnyOrgOrPersonalUiTest/AnyOrgOrPersonalUiTest.csproj
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFrameworks>net8.0</TargetFrameworks> | ||
<IsPackable>false</IsPackable> | ||
<Nullable>enable</Nullable> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="$(MicrosoftAspNetCoreMvcTestingVersion)" /> | ||
<PackageReference Include="Microsoft.Identity.Lab.Api" Version="$(MicrosoftIdentityLabApiVersion)" /> | ||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNetTestSdkVersion)" /> | ||
<PackageReference Include="Microsoft.Playwright" Version="$(MicrosoftPlaywrightVersion)" /> | ||
<PackageReference Include="System.Management" Version="$(SystemManagementVersion)" /> | ||
<PackageReference Include="System.Text.Json" Version="$(SystemTextJsonVersion)" /> | ||
<PackageReference Include="xunit" Version="$(XunitVersion)" /> | ||
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitRunnerVisualStudioVersion)"> | ||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
<PrivateAssets>all</PrivateAssets> | ||
</PackageReference> | ||
<PackageReference Include="coverlet.collector" Version="$(CoverletCollectorVersion)"> | ||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
<PrivateAssets>all</PrivateAssets> | ||
</PackageReference> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\Common\Common.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
{ | ||
"AzureAd": { | ||
"Instance": "https://login.microsoftonline.com/", | ||
"Domain": "msidlab3.onmicrosoft.com", | ||
"TenantId": "8e44f19d-bbab-4a82-b76b-4cd0a6fbc97a", | ||
"ClientId": "d9cde0be-ad97-41e6-855e-2f85136671c1", | ||
"CallbackPath": "/signin-oidc", | ||
"SignedOutCallbackPath": "/signout-callback-oidc" | ||
}, | ||
"Logging": { | ||
"LogLevel": { | ||
"Default": "Information", | ||
"Microsoft": "Warning", | ||
"Microsoft.Hosting.Lifetime": "Information" | ||
} | ||
}, | ||
"AllowedHosts": "*" | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
<IsPackable>false</IsPackable> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="$(MicrosoftAspNetCoreMvcTestingVersion)" /> | ||
<PackageReference Include="Microsoft.Identity.Lab.Api" Version="$(MicrosoftIdentityLabApiVersion)" /> | ||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNetTestSdkVersion)" /> | ||
<PackageReference Include="Microsoft.Playwright" Version="$(MicrosoftPlaywrightVersion)" /> | ||
<PackageReference Include="System.Management" Version="$(SystemManagementVersion)" /> | ||
<PackageReference Include="System.Text.Json" Version="$(SystemTextJsonVersion)" /> | ||
<PackageReference Include="xunit" Version="$(XunitVersion)" /> | ||
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitRunnerVisualStudioVersion)"> | ||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
<PrivateAssets>all</PrivateAssets> | ||
</PackageReference> | ||
<PackageReference Include="coverlet.collector" Version="$(CoverletCollectorVersion)"> | ||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
<PrivateAssets>all</PrivateAssets> | ||
</PackageReference> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<Using Include="Xunit" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
JoshLozensky marked this conversation as resolved.
Show resolved
Hide resolved
|
||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace Common | ||
{ | ||
public static class TestConstants | ||
{ | ||
public const string AppSetttingsDotJson = "appsettings.json"; | ||
public const string ClientFilePrefix = "client_"; | ||
public const string EmailText = "Email"; | ||
public const string Headless = "headless"; | ||
public const string HeaderText = "Header"; | ||
public const string HttpStarColon = "http://*:"; | ||
public const string HttpsStarColon = "https://*:"; | ||
public const string KestrelEndpointEnvVar = "Kestrel:Endpoints:Http:Url"; | ||
public const string LocalhostUrl = @"https://localhost:"; | ||
public const string OIDCUser = "[email protected]"; | ||
public const string PasswordText = "Password"; | ||
public const string ServerFilePrefix = "server_"; | ||
public const string TodoTitle1 = "Testing create todo item"; | ||
public const string TodoTitle2 = "Testing edit todo item"; | ||
public const string WebAppCrashedString = $"The web app process has exited prematurely."; | ||
|
||
public static readonly string s_oidcWebAppExe = Path.DirectorySeparatorChar.ToString() + "WebApp-OpenIDConnect-DotNet.exe"; | ||
public static readonly string s_oidcWebAppPath = Path.DirectorySeparatorChar.ToString() + "WebApp-OpenIDConnect"; | ||
public static readonly string s_todoListClientExe = Path.DirectorySeparatorChar.ToString() + "TodoListClient.exe"; | ||
public static readonly string s_todoListClientPath = Path.DirectorySeparatorChar.ToString() + "Client"; | ||
public static readonly string s_todoListServiceExe = Path.DirectorySeparatorChar.ToString() + "TodoListService.exe"; | ||
public static readonly string s_todoListServicePath = Path.DirectorySeparatorChar.ToString() + "TodoListService"; | ||
} | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.