-
Notifications
You must be signed in to change notification settings - Fork 1k
B2C UI test #793
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
B2C UI test #793
Changes from all commits
Commits
Show all changes
27 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 871809c
added Ui test for multiple API sample
JoshLozensky fa3aa7b
updating for help with debugging
JoshLozensky 98db390
making draft PR
JoshLozensky cb4a500
adding temporary appsettings.json fix
JoshLozensky 3ace0dd
Created B2C UI test
JoshLozensky 25a9e4b
sort usings
JoshLozensky a68efab
Rebase onto main
JoshLozensky 0a4f825
updated test to use refactored helpers
JoshLozensky 9490e6e
removed extraneous comment
JoshLozensky 04cd23e
Added sample build logic to test
JoshLozensky b246a80
removing unneeded changes
JoshLozensky 6154bc0
Remove extra brace
JoshLozensky d264824
removing unneeded code
JoshLozensky a5c19a1
Merge branch 'lozensky/AddingB2cUiTest' of https://github.com/Azure-S…
JoshLozensky 9a58e06
removing duplicated file
JoshLozensky 5406c43
fixing spacing
JoshLozensky f15e6ec
Remove extra space
JoshLozensky 26c1dfc
setting headless to true
JoshLozensky b1ccd59
Merge branch 'lozensky/AddingB2cUiTest' of https://github.com/Azure-S…
JoshLozensky 0a6e26a
address PR feedback
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
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
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 |
---|---|---|
@@ -0,0 +1,147 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using Azure.Identity; | ||
using Common; | ||
using Microsoft.Identity.Lab.Api; | ||
using Microsoft.Playwright; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.IO; | ||
using System.Runtime.Versioning; | ||
using System.Threading.Tasks; | ||
using Xunit; | ||
using Xunit.Abstractions; | ||
using TC = Common.TestConstants; | ||
|
||
namespace B2CUiTest | ||
{ | ||
public class B2CUiTest : IClassFixture<InstallPlaywrightBrowserFixture> | ||
{ | ||
private const string KeyvaultEmailName = "IdWeb-B2C-user"; | ||
private const string KeyvaultPasswordName = "IdWeb-B2C-password"; | ||
private const string KeyvaultClientSecretName = "IdWeb-B2C-Client-ClientSecret"; | ||
private const string NameOfUser = "unknown"; | ||
private const uint ProcessStartupRetryNum = 3; | ||
private const string SampleSolutionFileName = "4-2-B2C-Secured-API.sln"; | ||
private const uint TodoListClientPort = 5000; | ||
private const uint TodoListServicePort = 44332; | ||
private const string TraceClassName = "B2C-Login"; | ||
|
||
private readonly LocatorAssertionsToBeVisibleOptions _assertVisibleOptions = new() { Timeout = 25000 }; | ||
private readonly string _sampleClientAppPath; | ||
private readonly string _samplePath = Path.Join("4-WebApp-your-API", "4-2-B2C"); | ||
private readonly string _sampleServiceAppPath; | ||
private readonly Uri _keyvaultUri = new("https://webappsapistests.vault.azure.net"); | ||
private readonly ITestOutputHelper _output; | ||
private readonly string _testAssemblyLocation = typeof(B2CUiTest).Assembly.Location; | ||
|
||
public B2CUiTest(ITestOutputHelper output) | ||
{ | ||
_output = output; | ||
_sampleClientAppPath = Path.Join(_samplePath, TC.s_todoListClientPath); | ||
_sampleServiceAppPath = Path.Join(_samplePath, TC.s_todoListServicePath); | ||
} | ||
|
||
[Fact] | ||
[SupportedOSPlatform("windows")] | ||
public async Task B2C_ValidCreds_LoginLogout() | ||
{ | ||
// Web app and api environmental variable setup. | ||
Dictionary<string, Process>? processes = null; | ||
DefaultAzureCredential azureCred = new(); | ||
string clientSecret = await UiTestHelpers.GetValueFromKeyvaultWitDefaultCreds(_keyvaultUri, KeyvaultClientSecretName, azureCred); | ||
var serviceEnvVars = new Dictionary<string, string> | ||
{ | ||
{"ASPNETCORE_ENVIRONMENT", "Development" }, | ||
{TC.KestrelEndpointEnvVar, TC.HttpStarColon + TodoListServicePort} | ||
}; | ||
var clientEnvVars = new Dictionary<string, string> | ||
{ | ||
{"ASPNETCORE_ENVIRONMENT", "Development"}, | ||
{"AzureAdB2C__ClientSecret", clientSecret}, | ||
{TC.KestrelEndpointEnvVar, TC.HttpsStarColon + TodoListClientPort} | ||
}; | ||
|
||
// Get email and password from keyvault. | ||
string email = await UiTestHelpers.GetValueFromKeyvaultWitDefaultCreds(_keyvaultUri, KeyvaultEmailName, azureCred); | ||
string password = await UiTestHelpers.GetValueFromKeyvaultWitDefaultCreds(_keyvaultUri, KeyvaultPasswordName, azureCred); | ||
|
||
// Playwright setup. To see browser UI, set 'Headless = false'. | ||
const string TraceFileName = TraceClassName + "_TodoAppFunctionsCorrectly"; | ||
using IPlaywright playwright = await Playwright.CreateAsync(); | ||
IBrowser browser = await playwright.Chromium.LaunchAsync(new() { Headless = true }); | ||
IBrowserContext context = await browser.NewContextAsync(new BrowserNewContextOptions { IgnoreHTTPSErrors = true }); | ||
await context.Tracing.StartAsync(new() { Screenshots = true, Snapshots = true, Sources = true }); | ||
|
||
try | ||
{ | ||
UiTestHelpers.BuildSampleUsingSampleAppsettings(_testAssemblyLocation, _samplePath, SampleSolutionFileName); | ||
|
||
// 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, _sampleClientAppPath, TC.s_todoListClientExe, clientEnvVars); // probs need to add client specific path | ||
var serviceProcessOptions = new ProcessStartOptions(_testAssemblyLocation, _sampleServiceAppPath, TC.s_todoListServiceExe, serviceEnvVars); | ||
|
||
UiTestHelpers.StartAndVerifyProcessesAreRunning([serviceProcessOptions, clientProcessOptions], out processes, ProcessStartupRetryNum); | ||
|
||
// Navigate to web app the retry logic ensures the web app has time to start up to establish a connection. | ||
IPage page = await context.NewPageAsync(); | ||
uint InitialConnectionRetryCount = 5; | ||
while (InitialConnectionRetryCount > 0) | ||
{ | ||
try | ||
{ | ||
await page.GotoAsync(TC.LocalhostUrl + TodoListClientPort); | ||
break; | ||
} | ||
catch (PlaywrightException) | ||
{ | ||
await Task.Delay(1000); | ||
InitialConnectionRetryCount--; | ||
if (InitialConnectionRetryCount == 0) { throw; } | ||
} | ||
} | ||
LabResponse labResponse = await LabUserHelper.GetB2CLocalAccountAsync(); | ||
|
||
// Initial sign in | ||
_output.WriteLine("Starting web app sign-in flow."); | ||
ILocator emailEntryBox = page.GetByPlaceholder("Email Address"); | ||
await emailEntryBox.FillAsync(email); | ||
await emailEntryBox.PressAsync("Tab"); | ||
await page.GetByPlaceholder("Password").FillAsync(password); | ||
await page.GetByRole(AriaRole.Button, new() { Name = "Sign in" }).ClickAsync(); | ||
await Assertions.Expect(page.GetByText("TodoList")).ToBeVisibleAsync(_assertVisibleOptions); | ||
await Assertions.Expect(page.GetByText(NameOfUser)).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(); | ||
_output.WriteLine("Signing out ..."); | ||
await Assertions.Expect(page.GetByText("You have successfully signed out.")).ToBeVisibleAsync(_assertVisibleOptions); | ||
await Assertions.Expect(page.GetByText(NameOfUser)).ToBeHiddenAsync(); | ||
_output.WriteLine("Web app sign out successful."); | ||
} | ||
catch (Exception ex) | ||
{ | ||
Assert.Fail($"the UI automation failed: {ex} output: {ex.Message}."); | ||
} | ||
finally | ||
{ | ||
// End all processes. | ||
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(); | ||
} | ||
} | ||
} | ||
} |
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> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Azure.Identity" Version="1.12.1" /> | ||
<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
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
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check the warning, there is one in the GitHub UI
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
enabled nullable in B2C UI test csproj