diff --git a/.azure/pipelines/helix-matrix.yml b/.azure/pipelines/helix-matrix.yml
index 558afc7bbaa2..520fb47cdf77 100644
--- a/.azure/pipelines/helix-matrix.yml
+++ b/.azure/pipelines/helix-matrix.yml
@@ -1,5 +1,9 @@
# We only want to run full helix matrix on main
-pr: none
+pr:
+ autoCancel: true
+ branches:
+ include:
+ - '*'
trigger: none
schedules:
# Cron timezone is UTC.
diff --git a/eng/helix/content/RunTests/Program.cs b/eng/helix/content/RunTests/Program.cs
index 349ab29b8a03..4de3d6537319 100644
--- a/eng/helix/content/RunTests/Program.cs
+++ b/eng/helix/content/RunTests/Program.cs
@@ -27,6 +27,12 @@ static async Task Main(string[] args)
{
keepGoing = runner.InstallAspNetRefIfNeeded();
}
+#if INSTALLPLAYWRIGHT
+ if (keepGoing)
+ {
+ keepGoing = await runner.InstallPlaywrightAsync();
+ }
+#endif
runner.DisplayContents();
diff --git a/eng/helix/content/RunTests/RunTests.csproj b/eng/helix/content/RunTests/RunTests.csproj
index 7fc0c8c63888..948c3b72dce6 100644
--- a/eng/helix/content/RunTests/RunTests.csproj
+++ b/eng/helix/content/RunTests/RunTests.csproj
@@ -3,9 +3,11 @@
Exe
net6.0
+ $(DefineConstants);INSTALLPLAYWRIGHT
+
diff --git a/eng/helix/content/RunTests/RunTestsOptions.cs b/eng/helix/content/RunTests/RunTestsOptions.cs
index 031326ba8a14..beaf08f19595 100644
--- a/eng/helix/content/RunTests/RunTestsOptions.cs
+++ b/eng/helix/content/RunTests/RunTestsOptions.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.CommandLine;
+using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
@@ -67,7 +68,7 @@ public static RunTestsOptions Parse(string[] args)
Quarantined = parseResult.ValueForOption("--quarantined"),
RuntimeVersion = sharedFxVersion,
Target = parseResult.ValueForOption("--target"),
- Timeout = TimeSpan.Parse(parseResult.ValueForOption("--helixTimeout")),
+ Timeout = TimeSpan.Parse(parseResult.ValueForOption("--helixTimeout"), CultureInfo.InvariantCulture),
// When targeting pack builds, it has exactly the same version as the shared framework.
AspNetRef = $"Microsoft.AspNetCore.App.Ref.{sharedFxVersion}.nupkg",
diff --git a/eng/helix/content/RunTests/TestRunner.cs b/eng/helix/content/RunTests/TestRunner.cs
index 2aeb1c5abca7..2a48452d7356 100644
--- a/eng/helix/content/RunTests/TestRunner.cs
+++ b/eng/helix/content/RunTests/TestRunner.cs
@@ -8,6 +8,9 @@
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
+#if INSTALLPLAYWRIGHT
+using PlaywrightSharp;
+#endif
namespace RunTests
{
@@ -40,6 +43,13 @@ public bool SetupEnvironment()
Console.WriteLine($"Set DotNetEfFullPath: {dotnetEFFullPath}");
EnvironmentVariables.Add("DotNetEfFullPath", dotnetEFFullPath);
+#if INSTALLPLAYWRIGHT
+ // Playwright will download and look for browsers to this directory
+ var playwrightBrowsers = Path.Combine(helixDir, "ms-playwright");
+ Console.WriteLine($"Setting PLAYWRIGHT_BROWSERS_PATH: {playwrightBrowsers}");
+ EnvironmentVariables.Add("PLAYWRIGHT_BROWSERS_PATH", playwrightBrowsers);
+#endif
+
Console.WriteLine($"Creating nuget restore directory: {nugetRestore}");
Directory.CreateDirectory(nugetRestore);
@@ -80,6 +90,23 @@ public void DisplayContents(string path = "./")
}
}
+#if INSTALLPLAYWRIGHT
+ public async Task InstallPlaywrightAsync()
+ {
+ try
+ {
+ Console.WriteLine($"Installing Playwright to {EnvironmentVariables["PLAYWRIGHT_BROWSERS_PATH"]}");
+ await Playwright.InstallAsync(EnvironmentVariables["PLAYWRIGHT_BROWSERS_PATH"]);
+ return true;
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine($"Exception installing playwright: {e.ToString()}");
+ return false;
+ }
+ }
+#endif
+
public async Task InstallAspNetAppIfNeededAsync()
{
try
@@ -136,6 +163,14 @@ await ProcessUtil.RunAsync($"{Options.DotnetRoot}/dotnet",
throwOnError: false,
cancellationToken: new CancellationTokenSource(TimeSpan.FromMinutes(2)).Token);
+ await ProcessUtil.RunAsync($"{Options.DotnetRoot}/dotnet",
+ $"tool install dotnet-serve --tool-path {Options.HELIX_WORKITEM_ROOT}",
+ environmentVariables: EnvironmentVariables,
+ outputDataReceived: Console.WriteLine,
+ errorDataReceived: Console.Error.WriteLine,
+ throwOnError: false,
+ cancellationToken: new CancellationTokenSource(TimeSpan.FromMinutes(2)).Token);
+
// ';' is the path separator on Windows, and ':' on Unix
Options.Path += OperatingSystem.IsWindows() ? ";" : ":";
Options.Path += $"{Environment.GetEnvironmentVariable("DOTNET_CLI_HOME")}/.dotnet/tools";
@@ -231,7 +266,7 @@ public async Task RunTestsAsync()
{
// Timeout test run 5 minutes before the Helix job would timeout
var cts = new CancellationTokenSource(Options.Timeout.Subtract(TimeSpan.FromMinutes(5)));
- var commonTestArgs = $"test {Options.Target} --logger:xunit --logger:\"console;verbosity=normal\" --blame \"CollectHangDump;TestTimeout=5m\"";
+ var commonTestArgs = $"test {Options.Target} --logger:xunit --logger:\"console;verbosity=normal\" --blame \"CollectHangDump;TestTimeout=15m\"";
if (Options.Quarantined)
{
Console.WriteLine("Running quarantined tests.");
diff --git a/eng/helix/content/installPlaywrightReqs.ps1 b/eng/helix/content/installPlaywrightReqs.ps1
new file mode 100644
index 000000000000..2342511cdb4c
--- /dev/null
+++ b/eng/helix/content/installPlaywrightReqs.ps1
@@ -0,0 +1,12 @@
+Write-Host "Set-ExecutionPolicy Bypass -Scope Process"
+Set-ExecutionPolicy Bypass -Scope Process
+if ((Get-WindowsOptionalFeature -FeatureName ServerMediaFoundation -Online).State -eq "Enabled") {
+ Write-Host "ServerMediaFoundation feature already enabled."
+} else {
+ Write-Host "Enable-WindowsOptionalFeature -Online -FeatureName ServerMediaFoundation (For Playwright)"
+ try {
+ Enable-WindowsOptionalFeature -Online -FeatureName ServerMediaFoundation
+ } catch {
+ Write-Host "Enable-WindowsOptionalFeature -Online -FeatureName ServerMediaFoundation threw an exception: $PSItem"
+ }
+}
diff --git a/eng/helix/content/runtests.ps1 b/eng/helix/content/runtests.ps1
index a6a7da67eede..2c0cb0b3a01b 100644
--- a/eng/helix/content/runtests.ps1
+++ b/eng/helix/content/runtests.ps1
@@ -8,11 +8,13 @@ param(
[string]$Quarantined,
[string]$EF,
[string]$HelixTimeout,
+ [string]$InstallPlaywright,
[string]$FeedCred
)
$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 1
$env:DOTNET_MULTILEVEL_LOOKUP = 0
+$env:PLAYWRIGHT_BROWSERS_PATH = "$currentDirectory\ms-playwright"
$currentDirectory = Get-Location
$envPath = "$env:PATH;$env:HELIX_CORRELATION_PAYLOAD\node\bin"
@@ -53,7 +55,6 @@ function InstallDotnetSDKAndRuntime([string]$Feed, [string]$FeedCredParam) {
Write-Host "Set PATH to: $env:PATH"
$success = InvokeInstallDotnet ". eng\common\tools.ps1; InstallDotNet $env:DOTNET_ROOT $SdkVersion $Arch `'`' `$true `'$Feed`' `'$FeedCredParam`' `$true"
-
if (!$success) {
Write-Host "Retrying..."
continue
@@ -79,15 +80,15 @@ if ([string]::IsNullOrEmpty($FeedCred)) {
InstallDotnetSDKAndRuntime "https://dotnetclimsrc.blob.core.windows.net/dotnet" $FeedCred
}
-Write-Host "Restore: dotnet restore RunTests\RunTests.csproj --ignore-failed-sources"
-dotnet restore RunTests\RunTests.csproj --ignore-failed-sources
+Write-Host "Restore: dotnet restore RunTests\RunTests.csproj --ignore-failed-sources /p:InstallPlaywright=$InstallPlaywright"
+dotnet restore RunTests\RunTests.csproj --ignore-failed-sources /p:InstallPlaywright=$InstallPlaywright
if ($LastExitCode -ne 0) {
exit $LastExitCode
}
-Write-Host "Running tests: dotnet run --no-restore --project RunTests\RunTests.csproj -- --target $Target --runtime $AspRuntimeVersion --queue $Queue --arch $Arch --quarantined $Quarantined --ef $EF --helixTimeout $HelixTimeout"
-dotnet run --no-restore --project RunTests\RunTests.csproj -- --target $Target --runtime $AspRuntimeVersion --queue $Queue --arch $Arch --quarantined $Quarantined --ef $EF --helixTimeout $HelixTimeout
+Write-Host "Running tests: dotnet run --no-restore /p:InstallPlaywright=$InstallPlaywright --project RunTests\RunTests.csproj -- --target $Target --runtime $AspRuntimeVersion --queue $Queue --arch $Arch --quarantined $Quarantined --ef $EF --helixTimeout $HelixTimeout"
+dotnet run --no-restore /p:InstallPlaywright=$InstallPlaywright --project RunTests\RunTests.csproj -- --target $Target --runtime $AspRuntimeVersion --queue $Queue --arch $Arch --quarantined $Quarantined --ef $EF --helixTimeout $HelixTimeout
Write-Host "Finished running tests: exit_code=$LastExitCode"
exit $LastExitCode
diff --git a/eng/helix/content/runtests.sh b/eng/helix/content/runtests.sh
index 30697a488fe5..1a6ee3a3125f 100644
--- a/eng/helix/content/runtests.sh
+++ b/eng/helix/content/runtests.sh
@@ -25,6 +25,9 @@ export DOTNET_CLI_HOME="$DIR/.home$RANDOM"
export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
+# Set playwright browser path
+export PLAYWRIGHT_BROWSERS_PATH="$DIR/ms-playwright"
+
RESET="\033[0m"
RED="\033[0;31m"
YELLOW="\033[0;33m"
@@ -49,7 +52,7 @@ if [[ -z "${10:-}" ]]; then
}
else
echo "InstallDotNet $DOTNET_ROOT $dotnet_sdk_version '' '' true https://dotnetclimsrc.blob.core.windows.net/dotnet ..."
- InstallDotNet $DOTNET_ROOT $dotnet_sdk_version "" "" true https://dotnetclimsrc.blob.core.windows.net/dotnet ${10} || {
+ InstallDotNet $DOTNET_ROOT $dotnet_sdk_version "" "" true https://dotnetclimsrc.blob.core.windows.net/dotnet ${11} || {
exit_code=$?
Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "dotnet-install.sh failed (exit code '$exit_code')." >&2
ExitWithExitCode $exit_code
@@ -57,7 +60,7 @@ else
echo
echo "InstallDotNet $DOTNET_ROOT $dotnet_runtime_version '' dotnet true https://dotnetclimsrc.blob.core.windows.net/dotnet ..."
- InstallDotNet $DOTNET_ROOT $dotnet_runtime_version "" dotnet true https://dotnetclimsrc.blob.core.windows.net/dotnet ${10} || {
+ InstallDotNet $DOTNET_ROOT $dotnet_runtime_version "" dotnet true https://dotnetclimsrc.blob.core.windows.net/dotnet ${11} || {
exit_code=$?
Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "dotnet-install.sh failed (exit code '$exit_code')." >&2
ExitWithExitCode $exit_code
diff --git a/eng/targets/Helix.Common.props b/eng/targets/Helix.Common.props
index 451a4d93834b..c3fe23fb1241 100644
--- a/eng/targets/Helix.Common.props
+++ b/eng/targets/Helix.Common.props
@@ -8,14 +8,6 @@
-
-
-
-
-
-
-
-
diff --git a/eng/targets/Helix.targets b/eng/targets/Helix.targets
index 955e68fd4add..9592591f1d87 100644
--- a/eng/targets/Helix.targets
+++ b/eng/targets/Helix.targets
@@ -8,6 +8,24 @@
+
+ Windows.7.Amd64.Open;Windows.81.Amd64.Open
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -163,8 +181,8 @@
SharedFxVersion because that's needed even when the targeting pack isn't building.
Use the BrowserDebugHost transport package as a sentinel for the non-shipping version of the NETCoreApp shared framework.
-->
- call runtests.cmd $(TargetFileName) $(NETCoreSdkVersion) $(MicrosoftNETCoreBrowserDebugHostTransportVersion) $(SharedFxVersion) $(_HelixFriendlyNameTargetQueue) $(TargetArchitecture) $(RunQuarantinedTests) $(DotnetEfVersion) $(HelixTimeout) $(DotNetRuntimeSourceFeedKey)
- ./runtests.sh $(TargetFileName) $(NETCoreSdkVersion) $(MicrosoftNETCoreBrowserDebugHostTransportVersion) $(SharedFxVersion) $(_HelixFriendlyNameTargetQueue) $(TargetArchitecture) $(RunQuarantinedTests) $(DotnetEfVersion) $(HelixTimeout) $(DotNetRuntimeSourceFeedKey)
+ call runtests.cmd $(TargetFileName) $(NETCoreSdkVersion) $(MicrosoftNETCoreBrowserDebugHostTransportVersion) $(SharedFxVersion) $(_HelixFriendlyNameTargetQueue) $(TargetArchitecture) $(RunQuarantinedTests) $(DotnetEfVersion) $(HelixTimeout) $(TestDependsOnPlaywright) $(DotNetRuntimeSourceFeedKey)
+ ./runtests.sh $(TargetFileName) $(NETCoreSdkVersion) $(MicrosoftNETCoreBrowserDebugHostTransportVersion) $(SharedFxVersion) $(_HelixFriendlyNameTargetQueue) $(TargetArchitecture) $(RunQuarantinedTests) $(DotnetEfVersion) $(HelixTimeout) $(TestDependsOnPlaywright) $(DotNetRuntimeSourceFeedKey)
$(HelixCommand)
$(HelixTimeout)
diff --git a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs
index de27f48c4cb6..0fc61a174167 100644
--- a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs
+++ b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs
@@ -8,6 +8,7 @@
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Microsoft.AspNetCore.BrowserTesting;
+using Microsoft.AspNetCore.Testing;
using PlaywrightSharp;
using ProjectTemplates.Tests.Infrastructure;
using Templates.Test.Helpers;
diff --git a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorTemplates.Tests.csproj b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorTemplates.Tests.csproj
index f932b3471666..8001d254d00c 100644
--- a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorTemplates.Tests.csproj
+++ b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorTemplates.Tests.csproj
@@ -6,10 +6,8 @@
true
true
-
- false
+ true
true
-
@@ -18,6 +16,8 @@
TestTemplates\
$([MSBuild]::EnsureTrailingSlash('$(RepoRoot)'))obj\template-restore\
true
+ true
+ true
diff --git a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorWasmTemplateTest.cs b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorWasmTemplateTest.cs
index 2f52d3e2aa30..abad1b3c4b4e 100644
--- a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorWasmTemplateTest.cs
+++ b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorWasmTemplateTest.cs
@@ -79,6 +79,8 @@ public async Task BlazorWasmStandaloneTemplate_Works(BrowserKind browserKind)
EnsureBrowserAvailable(browserKind);
}
}
+
+ Assert.True(0 == 1, "Fail to get logs");
}
private async Task NavigateToPage(IBrowserContext browser, string listeningUri)
@@ -654,7 +656,19 @@ private void UpdatePublishedSettings(Project serverProject)
Output.WriteLine("Running dotnet serve on published output...");
var developmentCertificate = DevelopmentCertificate.Create(project.TemplateOutputDir);
- var serveProcess = ProcessEx.Run(Output, publishDir, DotNetMuxer.MuxerPathOrDefault(), $"serve -S --pfx \"{developmentCertificate.CertificatePath}\" --pfx-pwd \"{developmentCertificate.CertificatePassword}\" --port 0");
+ var args = $"-S --pfx \"{developmentCertificate.CertificatePath}\" --pfx-pwd \"{developmentCertificate.CertificatePassword}\" --port 0";
+ var command = DotNetMuxer.MuxerPathOrDefault();
+ if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("HELIX_DIR")))
+ {
+ args = $"serve " + args;
+ }
+ else
+ {
+ command = "dotnet-serve";
+ args = "--roll-forward LatestMajor " + args; // dotnet-serve targets net5.0 by default
+ }
+
+ var serveProcess = ProcessEx.Run(Output, publishDir, command, args);
var listeningUri = ResolveListeningUrl(serveProcess);
return (serveProcess, listeningUri);
}
diff --git a/src/ProjectTemplates/Shared/Project.cs b/src/ProjectTemplates/Shared/Project.cs
index 68af9da053a1..bf2d1082587b 100644
--- a/src/ProjectTemplates/Shared/Project.cs
+++ b/src/ProjectTemplates/Shared/Project.cs
@@ -231,11 +231,7 @@ internal async Task RunDotNetEfUpdateDatabaseAsync()
{
var assembly = typeof(ProjectFactoryFixture).Assembly;
- var dotNetEfFullPath = assembly.GetCustomAttributes()
- .First(attribute => attribute.Key == "DotNetEfFullPath")
- .Value;
-
- var args = $"\"{dotNetEfFullPath}\" --verbose --no-build database update";
+ var args = "--verbose --no-build database update";
// Only run one instance of 'dotnet new' at once, as a workaround for
// https://github.com/aspnet/templating/issues/63
@@ -243,7 +239,17 @@ internal async Task RunDotNetEfUpdateDatabaseAsync()
try
{
Output.WriteLine("Acquired DotNetNewLock");
- using var result = ProcessEx.Run(Output, TemplateOutputDir, DotNetMuxer.MuxerPathOrDefault(), args);
+ var command = DotNetMuxer.MuxerPathOrDefault();
+ if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("DotNetEfFullPath")))
+ {
+ args = $"\"{DotNetEfFullPath}\" " + args;
+ }
+ else
+ {
+ command = "dotnet-ef";
+ }
+
+ using var result = ProcessEx.Run(Output, TemplateOutputDir, command, args);
await result.Exited;
return new ProcessResult(result);
}
diff --git a/src/Servers/IIS/IIS/test/Directory.Build.props b/src/Servers/IIS/IIS/test/Directory.Build.props
index 6f6f92116853..8b196e74ad18 100644
--- a/src/Servers/IIS/IIS/test/Directory.Build.props
+++ b/src/Servers/IIS/IIS/test/Directory.Build.props
@@ -8,6 +8,7 @@
true
+ true
diff --git a/src/Shared/BrowserTesting/src/BrowserManager.cs b/src/Shared/BrowserTesting/src/BrowserManager.cs
index ede459195318..20f970736e27 100644
--- a/src/Shared/BrowserTesting/src/BrowserManager.cs
+++ b/src/Shared/BrowserTesting/src/BrowserManager.cs
@@ -46,7 +46,7 @@ private async Task InitializeAsync()
async Task InitializeCore()
{
- Playwright = await PlaywrightSharp.Playwright.CreateAsync(_loggerFactory, debug: "pw:api");
+ Playwright = await PlaywrightSharp.Playwright.CreateAsync(_loggerFactory/*, debug: "pw:api"*/);
foreach (var (browserName, options) in _browserManagerConfiguration.BrowserOptions)
{
if (!_launchBrowsers.ContainsKey(browserName))
diff --git a/src/Shared/BrowserTesting/src/ContextInformation.cs b/src/Shared/BrowserTesting/src/ContextInformation.cs
index 07cadc4bf0f5..7aec84d972de 100644
--- a/src/Shared/BrowserTesting/src/ContextInformation.cs
+++ b/src/Shared/BrowserTesting/src/ContextInformation.cs
@@ -55,10 +55,25 @@ internal BrowserContextOptions ConfigureUniqueHarPath(BrowserContextOptions brow
if (browserContextOptions?.RecordHar?.Path != null)
{
var identifier = Guid.NewGuid().ToString("N");
- browserContextOptions.RecordHar.Path = Path.Combine(browserContextOptions.RecordHar.Path, $"{identifier}.har");
+ var harDirectory = Environment.GetEnvironmentVariable("HELIX_WORKITEM_UPLOAD_ROOT");
+ if (string.IsNullOrEmpty(harDirectory))
+ {
+ harDirectory = browserContextOptions.RecordHar.Path;
+ }
+
+ browserContextOptions.RecordHar.Path = Path.Combine(harDirectory, $"{identifier}.har");
_harPath = browserContextOptions.RecordHar.Path;
}
+ if (browserContextOptions?.RecordVideo?.Dir != null)
+ {
+ var uploadDir = Environment.GetEnvironmentVariable("HELIX_WORKITEM_UPLOAD_ROOT");
+ if (!string.IsNullOrEmpty(uploadDir))
+ {
+ browserContextOptions.RecordVideo.Dir = uploadDir;
+ }
+ }
+
return browserContextOptions;
}
}