From 8a242c0d9e78578b6a304acf7b32e190d06eecf9 Mon Sep 17 00:00:00 2001 From: Siddharth Singha Roy Date: Tue, 12 Nov 2024 00:27:29 +0530 Subject: [PATCH 1/2] chore(playwrighttesting): populate NumberOfTestWorkers from runsettings and refactor PlaywrightReporter --- .../src/Constants.cs | 5 + .../src/Implementation/EnvironmentHandler.cs | 26 ++ .../src/Implementation/XmlRunSettings.cs | 49 ++++ .../src/Interface/IEnvironment.cs | 12 + .../src/Interface/IXmlRunSettings.cs | 13 + .../src/Model/CloudRunMetadata.cs | 1 + .../src/PlaywrightReporter.cs | 67 +++-- .../src/PlaywrightService.cs | 6 +- .../src/PlaywrightServiceOptions.cs | 4 +- .../src/Processor/DataProcessor.cs | 4 +- .../src/Processor/TestProcessor.cs | 4 +- .../src/Utility/CiInfoProvider.cs | 105 +++---- .../Implementation/XmlRunSettingsTests.cs | 58 ++++ .../tests/PlaywrightReporterTests.cs | 266 ++++++++++++++++++ .../tests/Processor/DataProcessorTests.cs | 8 +- 15 files changed, 541 insertions(+), 87 deletions(-) create mode 100644 sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Implementation/EnvironmentHandler.cs create mode 100644 sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Implementation/XmlRunSettings.cs create mode 100644 sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Interface/IEnvironment.cs create mode 100644 sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Interface/IXmlRunSettings.cs create mode 100644 sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/tests/Implementation/XmlRunSettingsTests.cs create mode 100644 sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/tests/PlaywrightReporterTests.cs diff --git a/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Constants.cs b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Constants.cs index 6b2559845d2f5..6eee7b7d13f34 100644 --- a/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Constants.cs +++ b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Constants.cs @@ -180,6 +180,11 @@ public class RunSettingKey /// Enable Result publish. /// public static readonly string EnableResultPublish = "EnableResultPublish"; + + /// + /// Number of NUnit test workers. + /// + public static readonly string NumberOfTestWorkers = "NumberOfTestWorkers"; } internal class Constants diff --git a/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Implementation/EnvironmentHandler.cs b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Implementation/EnvironmentHandler.cs new file mode 100644 index 0000000000000..704cc8ac077df --- /dev/null +++ b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Implementation/EnvironmentHandler.cs @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.Interface; + +namespace Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.Implementation +{ + internal class EnvironmentHandler : IEnvironment + { + public void Exit(int exitCode) + { + Environment.Exit(exitCode); + } + + public string GetEnvironmentVariable(string variable) + { + return Environment.GetEnvironmentVariable(variable); + } + + public void SetEnvironmentVariable(string variable, string value) + { + Environment.SetEnvironmentVariable(variable, value); + } + } +} diff --git a/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Implementation/XmlRunSettings.cs b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Implementation/XmlRunSettings.cs new file mode 100644 index 0000000000000..238f1523e7b99 --- /dev/null +++ b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Implementation/XmlRunSettings.cs @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Xml; +using Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.Interface; +using Microsoft.VisualStudio.TestPlatform.ObjectModel.Utilities; + +namespace Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.Implementation +{ + internal class XmlRunSettings : IXmlRunSettings + { + private static readonly string NUnitNodeName = "NUnit"; + public Dictionary GetTestRunParameters(string? settingsXml) + { + return XmlRunSettingsUtilities.GetTestRunParameters(settingsXml); + } + + public Dictionary GetNUnitParameters(string? settingsXml) + { + try + { + var parameters = new Dictionary(); + XmlDocument xmlDocument = ParseXmlSettings(settingsXml); + XmlNodeList nUnitNodes = xmlDocument.GetElementsByTagName(NUnitNodeName); + foreach (XmlNode nUnitNode in nUnitNodes) + { + foreach (XmlNode childNode in nUnitNode.ChildNodes) + { + parameters.Add(childNode.Name, childNode.InnerText); + } + } + return parameters; + } + catch (Exception) + { + return new Dictionary(); + } + } + + private static XmlDocument ParseXmlSettings(string? settingsXml) + { + XmlDocument xmlDocument = new(); + xmlDocument.LoadXml(settingsXml); + return xmlDocument; + } + } +} diff --git a/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Interface/IEnvironment.cs b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Interface/IEnvironment.cs new file mode 100644 index 0000000000000..71fc07a8d701c --- /dev/null +++ b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Interface/IEnvironment.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.Interface +{ + internal interface IEnvironment + { + void Exit(int exitCode); + string GetEnvironmentVariable(string variable); + void SetEnvironmentVariable(string variable, string value); + } +} diff --git a/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Interface/IXmlRunSettings.cs b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Interface/IXmlRunSettings.cs new file mode 100644 index 0000000000000..70d3b9d00c73d --- /dev/null +++ b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Interface/IXmlRunSettings.cs @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; + +namespace Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.Interface +{ + internal interface IXmlRunSettings + { + Dictionary GetTestRunParameters(string? settingsXml); + Dictionary GetNUnitParameters(string? settingsXml); + } +} diff --git a/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Model/CloudRunMetadata.cs b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Model/CloudRunMetadata.cs index 124eed6ab0ce7..4e4f419248512 100644 --- a/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Model/CloudRunMetadata.cs +++ b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Model/CloudRunMetadata.cs @@ -18,5 +18,6 @@ internal string? PortalUrl internal bool EnableGithubSummary { get; set; } = true; internal DateTime TestRunStartTime { get; set; } internal TokenDetails? AccessTokenDetails { get; set; } + internal int NumberOfTestWorkers { get; set; } = 1; } } diff --git a/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/PlaywrightReporter.cs b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/PlaywrightReporter.cs index bfb6d6fdccb3b..670b5a5aa1bfd 100644 --- a/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/PlaywrightReporter.cs +++ b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/PlaywrightReporter.cs @@ -12,6 +12,8 @@ using Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.Interface; using Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.Implementation; using Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.Processor; +using Microsoft.IdentityModel.JsonWebTokens; +using Microsoft.IdentityModel.Tokens; namespace Azure.Developer.MicrosoftPlaywrightTesting.TestLogger; @@ -19,15 +21,23 @@ namespace Azure.Developer.MicrosoftPlaywrightTesting.TestLogger; [ExtensionUri("logger://MicrosoftPlaywrightTesting/Logger/v1")] internal class PlaywrightReporter : ITestLoggerWithParameters { - private Dictionary? _parametersDictionary; - private PlaywrightService? _playwrightService; - private readonly ILogger _logger; - private TestProcessor? _testProcessor; - - public PlaywrightReporter() : this(null) { } // no-op - public PlaywrightReporter(ILogger? logger) + internal Dictionary? _parametersDictionary; + internal PlaywrightService? _playwrightService; + internal TestProcessor? _testProcessor; + internal readonly ILogger _logger; + internal IEnvironment _environment; + internal IXmlRunSettings _xmlRunSettings; + internal IConsoleWriter _consoleWriter; + internal JsonWebTokenHandler _jsonWebTokenHandler; + + public PlaywrightReporter() : this(null, null, null, null, null) { } // no-op + public PlaywrightReporter(ILogger? logger, IEnvironment? environment, IXmlRunSettings? xmlRunSettings, IConsoleWriter? consoleWriter, JsonWebTokenHandler? jsonWebTokenHandler) { _logger = logger ?? new Logger(); + _environment = environment ?? new EnvironmentHandler(); + _xmlRunSettings = xmlRunSettings ?? new XmlRunSettings(); + _consoleWriter = consoleWriter ?? new ConsoleWriter(); + _jsonWebTokenHandler = jsonWebTokenHandler ?? new JsonWebTokenHandler(); } public void Initialize(TestLoggerEvents events, Dictionary parameters) @@ -66,18 +76,19 @@ internal void TestRunCompleteHandler(object? sender, TestRunCompleteEventArgs e) } #endregion - private void InitializePlaywrightReporter(string xmlSettings) + internal void InitializePlaywrightReporter(string xmlSettings) { - Dictionary runParameters = XmlRunSettingsUtilities.GetTestRunParameters(xmlSettings); + Dictionary runParameters = _xmlRunSettings.GetTestRunParameters(xmlSettings); + Dictionary nunitParameters = _xmlRunSettings.GetNUnitParameters(xmlSettings); runParameters.TryGetValue(RunSettingKey.RunId, out var runId); // If run id is not provided and not set via env, try fetching it from CI info. - CIInfo cIInfo = CiInfoProvider.GetCIInfo(); - if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable(ServiceEnvironmentVariable.PlaywrightServiceRunId))) + CIInfo cIInfo = CiInfoProvider.GetCIInfo(_environment); + if (string.IsNullOrEmpty(_environment.GetEnvironmentVariable(ServiceEnvironmentVariable.PlaywrightServiceRunId))) { if (string.IsNullOrEmpty(runId?.ToString())) - Environment.SetEnvironmentVariable(ServiceEnvironmentVariable.PlaywrightServiceRunId, ReporterUtils.GetRunId(cIInfo)); + _environment.SetEnvironmentVariable(ServiceEnvironmentVariable.PlaywrightServiceRunId, ReporterUtils.GetRunId(cIInfo)); else - Environment.SetEnvironmentVariable(ServiceEnvironmentVariable.PlaywrightServiceRunId, runId!.ToString()); + _environment.SetEnvironmentVariable(ServiceEnvironmentVariable.PlaywrightServiceRunId, runId!.ToString()); } else { @@ -89,46 +100,49 @@ private void InitializePlaywrightReporter(string xmlSettings) runParameters.TryGetValue(RunSettingKey.ManagedIdentityClientId, out var managedIdentityClientId); runParameters.TryGetValue(RunSettingKey.EnableGitHubSummary, out var enableGithubSummary); runParameters.TryGetValue(RunSettingKey.EnableResultPublish, out var enableResultPublish); + nunitParameters.TryGetValue(RunSettingKey.NumberOfTestWorkers, out var numberOfTestWorkers); string? enableGithubSummaryString = enableGithubSummary?.ToString(); string? enableResultPublishString = enableResultPublish?.ToString(); bool _enableGitHubSummary = string.IsNullOrEmpty(enableGithubSummaryString) || bool.Parse(enableGithubSummaryString!); bool _enableResultPublish = string.IsNullOrEmpty(enableResultPublishString) || bool.Parse(enableResultPublishString!); - PlaywrightServiceOptions? playwrightServiceSettings = null; + PlaywrightServiceOptions? playwrightServiceSettings; try { playwrightServiceSettings = new(runId: runId?.ToString(), serviceAuth: serviceAuth?.ToString(), azureTokenCredentialType: azureTokenCredential?.ToString(), managedIdentityClientId: managedIdentityClientId?.ToString()); } catch (Exception ex) { - Console.Error.WriteLine("Failed to initialize PlaywrightServiceSettings: " + ex); - Environment.Exit(1); + _consoleWriter.WriteError("Failed to initialize PlaywrightServiceSettings: " + ex); + _environment.Exit(1); + return; } - // setup entra rotation handlers - _playwrightService = new PlaywrightService(null, playwrightServiceSettings!.RunId, null, playwrightServiceSettings.ServiceAuth, null, playwrightServiceSettings.AzureTokenCredential); + _playwrightService = new PlaywrightService(null, playwrightServiceSettings!.RunId, null, playwrightServiceSettings.ServiceAuth, null, entraLifecycle: null, jsonWebTokenHandler: _jsonWebTokenHandler, credential: playwrightServiceSettings.AzureTokenCredential); #pragma warning disable AZC0102 // Do not use GetAwaiter().GetResult(). Use the TaskExtensions.EnsureCompleted() extension method instead. _playwrightService.InitializeAsync().GetAwaiter().GetResult(); #pragma warning restore AZC0102 // Do not use GetAwaiter().GetResult(). Use the TaskExtensions.EnsureCompleted() extension method instead. - var cloudRunId = Environment.GetEnvironmentVariable(ServiceEnvironmentVariable.PlaywrightServiceRunId); - string baseUrl = Environment.GetEnvironmentVariable(ReporterConstants.s_pLAYWRIGHT_SERVICE_REPORTING_URL); - string accessToken = Environment.GetEnvironmentVariable(ServiceEnvironmentVariable.PlaywrightServiceAccessToken); + var cloudRunId = _environment.GetEnvironmentVariable(ServiceEnvironmentVariable.PlaywrightServiceRunId); + string baseUrl = _environment.GetEnvironmentVariable(ReporterConstants.s_pLAYWRIGHT_SERVICE_REPORTING_URL); + string accessToken = _environment.GetEnvironmentVariable(ServiceEnvironmentVariable.PlaywrightServiceAccessToken); if (string.IsNullOrEmpty(baseUrl)) { - Console.Error.WriteLine(Constants.s_no_service_endpoint_error_message); - Environment.Exit(1); + _consoleWriter.WriteError(Constants.s_no_service_endpoint_error_message); + _environment.Exit(1); + return; } if (string.IsNullOrEmpty(accessToken)) { - Console.Error.WriteLine(Constants.s_no_auth_error); - Environment.Exit(1); + _consoleWriter.WriteError(Constants.s_no_auth_error); + _environment.Exit(1); + return; } var baseUri = new Uri(baseUrl); var reporterUtils = new ReporterUtils(); - TokenDetails tokenDetails = reporterUtils.ParseWorkspaceIdFromAccessToken(jsonWebTokenHandler: null, accessToken: accessToken); + TokenDetails tokenDetails = reporterUtils.ParseWorkspaceIdFromAccessToken(jsonWebTokenHandler: _jsonWebTokenHandler, accessToken: accessToken); var workspaceId = tokenDetails.aid; var cloudRunMetadata = new CloudRunMetadata @@ -140,6 +154,7 @@ private void InitializePlaywrightReporter(string xmlSettings) EnableGithubSummary = _enableGitHubSummary, TestRunStartTime = DateTime.UtcNow, AccessTokenDetails = tokenDetails, + NumberOfTestWorkers = numberOfTestWorkers != null ? Convert.ToInt32(numberOfTestWorkers) : 1 }; _testProcessor = new TestProcessor(cloudRunMetadata, cIInfo); diff --git a/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/PlaywrightService.cs b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/PlaywrightService.cs index 1a50d42912ec0..76633de822ba1 100644 --- a/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/PlaywrightService.cs +++ b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/PlaywrightService.cs @@ -79,8 +79,8 @@ internal PlaywrightService(OSPlatform? os = null, string? runId = null, string? { if (string.IsNullOrEmpty(ServiceEndpoint)) return; - _entraLifecycle = entraLifecycle ?? new EntraLifecycle(credential); _jsonWebTokenHandler = jsonWebTokenHandler ?? new JsonWebTokenHandler(); + _entraLifecycle = entraLifecycle ?? new EntraLifecycle(credential, _jsonWebTokenHandler); InitializePlaywrightServiceEnvironmentVariables(getServiceCompatibleOs(os), runId, exposeNetwork, serviceAuth, useCloudHostedBrowsers); } @@ -248,12 +248,12 @@ private void ValidateMptPAT() if (string.IsNullOrEmpty(authToken)) throw new Exception(Constants.s_no_auth_error); JsonWebToken jsonWebToken = _jsonWebTokenHandler!.ReadJsonWebToken(authToken) ?? throw new Exception(Constants.s_invalid_mpt_pat_error); - var tokenaWorkspaceId = jsonWebToken.Claims.FirstOrDefault(c => c.Type == "aid")?.Value; + var tokenWorkspaceId = jsonWebToken.Claims.FirstOrDefault(c => c.Type == "aid")?.Value; Match match = Regex.Match(ServiceEndpoint, @"wss://(?[\w-]+)\.api\.(?playwright(?:-test|-int)?\.io|playwright\.microsoft\.com)/accounts/(?[\w-]+)/"); if (!match.Success) throw new Exception(Constants.s_invalid_service_endpoint_error_message); var serviceEndpointWorkspaceId = match.Groups["workspaceId"].Value; - if (tokenaWorkspaceId != serviceEndpointWorkspaceId) + if (tokenWorkspaceId != serviceEndpointWorkspaceId) throw new Exception(Constants.s_workspace_mismatch_error); var expiry = (long)(jsonWebToken.ValidTo - new DateTime(1970, 1, 1)).TotalSeconds; if (expiry <= DateTimeOffset.UtcNow.ToUnixTimeSeconds()) diff --git a/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/PlaywrightServiceOptions.cs b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/PlaywrightServiceOptions.cs index 5eb7a1ecf63b7..7ba6a71070faf 100644 --- a/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/PlaywrightServiceOptions.cs +++ b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/PlaywrightServiceOptions.cs @@ -45,11 +45,11 @@ private void Validate() { if (Os != null && Os != OSPlatform.Linux && Os != OSPlatform.Windows) { - throw new System.Exception($"Invalid value for {nameof(Os)}: {Os}. Supported values are {ServiceOs.Linux} and {ServiceOs.Windows}"); + throw new Exception($"Invalid value for {nameof(Os)}: {Os}. Supported values are {ServiceOs.Linux} and {ServiceOs.Windows}"); } if (!string.IsNullOrEmpty(ServiceAuth) && ServiceAuth != ServiceAuthType.EntraId && ServiceAuth != ServiceAuthType.AccessToken) { - throw new System.Exception($"Invalid value for {nameof(ServiceAuth)}: {ServiceAuth}. Supported values are {ServiceAuthType.EntraId} and {ServiceAuthType.AccessToken}"); + throw new Exception($"Invalid value for {nameof(ServiceAuth)}: {ServiceAuth}. Supported values are {ServiceAuthType.EntraId} and {ServiceAuthType.AccessToken}"); } } diff --git a/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Processor/DataProcessor.cs b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Processor/DataProcessor.cs index 4160b862d8729..86d836e9783e0 100644 --- a/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Processor/DataProcessor.cs +++ b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Processor/DataProcessor.cs @@ -49,7 +49,7 @@ public TestRunDto GetTestRun() }, TestRunConfig = new ClientConfig // TODO fetch some of these dynamically { - Workers = 1, + Workers = _cloudRunMetadata.NumberOfTestWorkers, PwVersion = "1.40", Timeout = 60000, TestType = "WebTest", @@ -74,7 +74,7 @@ public TestRunShardDto GetTestRunShard() Status = "RUNNING", StartTime = startTime, }, - Workers = 1 + Workers = _cloudRunMetadata.NumberOfTestWorkers }; return shard; } diff --git a/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Processor/TestProcessor.cs b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Processor/TestProcessor.cs index 44320035a8c57..06af415402f60 100644 --- a/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Processor/TestProcessor.cs +++ b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Processor/TestProcessor.cs @@ -28,8 +28,8 @@ internal class TestProcessor : ITestProcessor private readonly ICloudRunErrorParser _cloudRunErrorParser; private readonly IServiceClient _serviceClient; private readonly IConsoleWriter _consoleWriter; - private readonly CIInfo _cIInfo; - private readonly CloudRunMetadata _cloudRunMetadata; + internal readonly CIInfo _cIInfo; + internal readonly CloudRunMetadata _cloudRunMetadata; private readonly IBlobService _blobService; // Test Metadata diff --git a/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Utility/CiInfoProvider.cs b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Utility/CiInfoProvider.cs index fa229851e41d3..39cd836f0264c 100644 --- a/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Utility/CiInfoProvider.cs +++ b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/src/Utility/CiInfoProvider.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.Implementation; +using Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.Interface; using Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.Model; using System; @@ -8,48 +10,51 @@ namespace Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.Utility; internal class CiInfoProvider { - private static bool IsGitHubActions() + private static bool IsGitHubActions(IEnvironment? environment = null) { - return Environment.GetEnvironmentVariable("GITHUB_ACTIONS") == "true"; + environment ??= new EnvironmentHandler(); + return environment.GetEnvironmentVariable("GITHUB_ACTIONS") == "true"; } - private static bool IsAzureDevOps() + private static bool IsAzureDevOps(IEnvironment? environment = null) { - return Environment.GetEnvironmentVariable("AZURE_HTTP_USER_AGENT") != null && - Environment.GetEnvironmentVariable("TF_BUILD") != null; + environment ??= new EnvironmentHandler(); + return environment.GetEnvironmentVariable("AZURE_HTTP_USER_AGENT") != null && + environment.GetEnvironmentVariable("TF_BUILD") != null; } - internal static string GetCIProvider() + internal static string GetCIProvider(IEnvironment? environment = null) { - if (IsGitHubActions()) + if (IsGitHubActions(environment)) return CIConstants.s_gITHUB_ACTIONS; - else if (IsAzureDevOps()) + else if (IsAzureDevOps(environment)) return CIConstants.s_aZURE_DEVOPS; else return CIConstants.s_dEFAULT; } - internal static CIInfo GetCIInfo() + internal static CIInfo GetCIInfo(IEnvironment? environment = null) { - string ciProvider = GetCIProvider(); + environment ??= new EnvironmentHandler(); + string ciProvider = GetCIProvider(environment); if (ciProvider == CIConstants.s_gITHUB_ACTIONS) { // Logic to get GitHub Actions CIInfo return new CIInfo { Provider = CIConstants.s_gITHUB_ACTIONS, - Repo = Environment.GetEnvironmentVariable("GITHUB_REPOSITORY_ID"), - Branch = GetGHBranchName(), - Author = Environment.GetEnvironmentVariable("GITHUB_ACTOR"), - CommitId = Environment.GetEnvironmentVariable("GITHUB_SHA"), - RevisionUrl = Environment.GetEnvironmentVariable("GITHUB_SERVER_URL") != null - ? $"{Environment.GetEnvironmentVariable("GITHUB_SERVER_URL")}/{Environment.GetEnvironmentVariable("GITHUB_REPOSITORY")}/commit/{Environment.GetEnvironmentVariable("GITHUB_SHA")}" + Repo = environment.GetEnvironmentVariable("GITHUB_REPOSITORY_ID"), + Branch = GetGHBranchName(environment), + Author = environment.GetEnvironmentVariable("GITHUB_ACTOR"), + CommitId = environment.GetEnvironmentVariable("GITHUB_SHA"), + RevisionUrl = environment.GetEnvironmentVariable("GITHUB_SERVER_URL") != null + ? $"{environment.GetEnvironmentVariable("GITHUB_SERVER_URL")}/{environment.GetEnvironmentVariable("GITHUB_REPOSITORY")}/commit/{environment.GetEnvironmentVariable("GITHUB_SHA")}" : null, - RunId = Environment.GetEnvironmentVariable("GITHUB_RUN_ID"), - RunAttempt = Environment.GetEnvironmentVariable("GITHUB_RUN_ATTEMPT") != null - ? int.Parse(Environment.GetEnvironmentVariable("GITHUB_RUN_ATTEMPT")!) + RunId = environment.GetEnvironmentVariable("GITHUB_RUN_ID"), + RunAttempt = environment.GetEnvironmentVariable("GITHUB_RUN_ATTEMPT") != null + ? int.Parse(environment.GetEnvironmentVariable("GITHUB_RUN_ATTEMPT")!) : null, - JobId = Environment.GetEnvironmentVariable("GITHUB_JOB") + JobId = environment.GetEnvironmentVariable("GITHUB_JOB") }; } else if (ciProvider == CIConstants.s_aZURE_DEVOPS) @@ -58,18 +63,18 @@ internal static CIInfo GetCIInfo() return new CIInfo { Provider = CIConstants.s_aZURE_DEVOPS, - Repo = Environment.GetEnvironmentVariable("BUILD_REPOSITORY_ID"), - Branch = Environment.GetEnvironmentVariable("BUILD_SOURCEBRANCH"), - Author = Environment.GetEnvironmentVariable("BUILD_REQUESTEDFOR"), - CommitId = Environment.GetEnvironmentVariable("BUILD_SOURCEVERSION"), - RevisionUrl = Environment.GetEnvironmentVariable("SYSTEM_TEAMFOUNDATIONCOLLECTIONURI") != null - ? $"{Environment.GetEnvironmentVariable("SYSTEM_TEAMFOUNDATIONCOLLECTIONURI")}{Environment.GetEnvironmentVariable("SYSTEM_TEAMPROJECT")}/_git/{Environment.GetEnvironmentVariable("BUILD_REPOSITORY_NAME")}/commit/{Environment.GetEnvironmentVariable("BUILD_SOURCEVERSION")}" + Repo = environment.GetEnvironmentVariable("BUILD_REPOSITORY_ID"), + Branch = environment.GetEnvironmentVariable("BUILD_SOURCEBRANCH"), + Author = environment.GetEnvironmentVariable("BUILD_REQUESTEDFOR"), + CommitId = environment.GetEnvironmentVariable("BUILD_SOURCEVERSION"), + RevisionUrl = environment.GetEnvironmentVariable("SYSTEM_TEAMFOUNDATIONCOLLECTIONURI") != null + ? $"{environment.GetEnvironmentVariable("SYSTEM_TEAMFOUNDATIONCOLLECTIONURI")}{environment.GetEnvironmentVariable("SYSTEM_TEAMPROJECT")}/_git/{environment.GetEnvironmentVariable("BUILD_REPOSITORY_NAME")}/commit/{environment.GetEnvironmentVariable("BUILD_SOURCEVERSION")}" : null, - RunId = GetADORunId(), - RunAttempt = Environment.GetEnvironmentVariable("RELEASE_ATTEMPTNUMBER") != null - ? int.Parse(Environment.GetEnvironmentVariable("RELEASE_ATTEMPTNUMBER")!) - : int.Parse(Environment.GetEnvironmentVariable("SYSTEM_JOBATTEMPT")!), - JobId = Environment.GetEnvironmentVariable("RELEASE_DEPLOYMENTID") ?? Environment.GetEnvironmentVariable("SYSTEM_JOBID") + RunId = GetADORunId(environment), + RunAttempt = environment.GetEnvironmentVariable("RELEASE_ATTEMPTNUMBER") != null + ? int.Parse(environment.GetEnvironmentVariable("RELEASE_ATTEMPTNUMBER")!) + : int.Parse(environment.GetEnvironmentVariable("SYSTEM_JOBATTEMPT")!), + JobId = environment.GetEnvironmentVariable("RELEASE_DEPLOYMENTID") ?? environment.GetEnvironmentVariable("SYSTEM_JOBID") }; } else @@ -78,34 +83,36 @@ internal static CIInfo GetCIInfo() return new CIInfo { Provider = CIConstants.s_dEFAULT, - Repo = Environment.GetEnvironmentVariable("REPO"), - Branch = Environment.GetEnvironmentVariable("BRANCH"), - Author = Environment.GetEnvironmentVariable("AUTHOR"), - CommitId = Environment.GetEnvironmentVariable("COMMIT_ID"), - RevisionUrl = Environment.GetEnvironmentVariable("REVISION_URL"), - RunId = Environment.GetEnvironmentVariable("RUN_ID"), - RunAttempt = Environment.GetEnvironmentVariable("RUN_ATTEMPT") != null - ? int.Parse(Environment.GetEnvironmentVariable("RUN_ATTEMPT")!) + Repo = environment.GetEnvironmentVariable("REPO"), + Branch = environment.GetEnvironmentVariable("BRANCH"), + Author = environment.GetEnvironmentVariable("AUTHOR"), + CommitId = environment.GetEnvironmentVariable("COMMIT_ID"), + RevisionUrl = environment.GetEnvironmentVariable("REVISION_URL"), + RunId = environment.GetEnvironmentVariable("RUN_ID"), + RunAttempt = environment.GetEnvironmentVariable("RUN_ATTEMPT") != null + ? int.Parse(environment.GetEnvironmentVariable("RUN_ATTEMPT")!) : null, - JobId = Environment.GetEnvironmentVariable("JOB_ID") + JobId = environment.GetEnvironmentVariable("JOB_ID") }; } } - private static string GetADORunId() + private static string GetADORunId(IEnvironment? environment = null) { - if (Environment.GetEnvironmentVariable("RELEASE_DEFINITIONID") != null && Environment.GetEnvironmentVariable("RELEASE_DEPLOYMENTID") != null) - return $"{Environment.GetEnvironmentVariable("RELEASE_DEFINITIONID")}-{Environment.GetEnvironmentVariable("RELEASE_DEPLOYMENTID")}"; + environment ??= new EnvironmentHandler(); + if (environment.GetEnvironmentVariable("RELEASE_DEFINITIONID") != null && environment.GetEnvironmentVariable("RELEASE_DEPLOYMENTID") != null) + return $"{environment.GetEnvironmentVariable("RELEASE_DEFINITIONID")}-{environment.GetEnvironmentVariable("RELEASE_DEPLOYMENTID")}"; else - return $"{Environment.GetEnvironmentVariable("SYSTEM_DEFINITIONID")}-{Environment.GetEnvironmentVariable("SYSTEM_JOBID")}"; + return $"{environment.GetEnvironmentVariable("SYSTEM_DEFINITIONID")}-{environment.GetEnvironmentVariable("SYSTEM_JOBID")}"; } - private static string GetGHBranchName() + private static string GetGHBranchName(IEnvironment? environment = null) { - if (Environment.GetEnvironmentVariable("GITHUB_EVENT_NAME") == "pull_request" || - Environment.GetEnvironmentVariable("GITHUB_EVENT_NAME") == "pull_request_target") - return Environment.GetEnvironmentVariable("GITHUB_HEAD_REF")!; + environment ??= new EnvironmentHandler(); + if (environment.GetEnvironmentVariable("GITHUB_EVENT_NAME") == "pull_request" || + environment.GetEnvironmentVariable("GITHUB_EVENT_NAME") == "pull_request_target") + return environment.GetEnvironmentVariable("GITHUB_HEAD_REF")!; else - return Environment.GetEnvironmentVariable("GITHUB_REF_NAME")!; + return environment.GetEnvironmentVariable("GITHUB_REF_NAME")!; } } diff --git a/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/tests/Implementation/XmlRunSettingsTests.cs b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/tests/Implementation/XmlRunSettingsTests.cs new file mode 100644 index 0000000000000..49f2f53c021f2 --- /dev/null +++ b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/tests/Implementation/XmlRunSettingsTests.cs @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.Implementation; +using System.Collections.Generic; + +namespace Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.Tests.Implementation +{ + [TestFixture] + [Parallelizable(ParallelScope.Self)] + internal class XmlRunSettingsTests + { + [Test] + public void GetNUnitParameters_WhenSettingsXmlContainsNUnitNode_ReturnsParameters() + { + var xmlRunSettings = new XmlRunSettings(); + var settingsXml = @"5False"; + + Dictionary parameters = xmlRunSettings.GetNUnitParameters(settingsXml); + + Assert.AreEqual(2, parameters.Count); + Assert.AreEqual(parameters["NumberOfTestWorkers"], "5"); + Assert.AreEqual(parameters["StopOnError"], "False"); + } + + [Test] + public void GetNUnitParameters_WhenSettingsXmlContainsInvalidNode_ReturnsEmptyDictionary() + { + var xmlRunSettings = new XmlRunSettings(); + var settingsXml = @"5 parameters = xmlRunSettings.GetNUnitParameters(settingsXml); + + Assert.AreEqual(0, parameters.Count); + } + + [Test] + public void GetNUnitParameters_WhenSettingsXmlDoesNotContainNUnitNode_ReturnsEmptyDictionary() + { + var xmlRunSettings = new XmlRunSettings(); + var settingsXml = @"5False"; + + Dictionary parameters = xmlRunSettings.GetNUnitParameters(settingsXml); + + Assert.AreEqual(0, parameters.Count); + } + + [Test] + public void GetNUnitParameters_WhenSettingsXmlIsNull_ReturnsEmptyDictionary() + { + var xmlRunSettings = new XmlRunSettings(); + + Dictionary parameters = xmlRunSettings.GetNUnitParameters(null); + + Assert.AreEqual(0, parameters.Count); + } + } +} diff --git a/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/tests/PlaywrightReporterTests.cs b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/tests/PlaywrightReporterTests.cs new file mode 100644 index 0000000000000..9f4d9efe8296b --- /dev/null +++ b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/tests/PlaywrightReporterTests.cs @@ -0,0 +1,266 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System; +using Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.Interface; +using Microsoft.IdentityModel.JsonWebTokens; +using Microsoft.IdentityModel.Tokens; +using Moq; +using Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.Utility; + +namespace Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.Tests +{ + [TestFixture] + internal class PlaywrightReporterTests + { + [TearDown] + public void TearDown() + { + Environment.SetEnvironmentVariable(ServiceEnvironmentVariable.PlaywrightServiceUri, null); + Environment.SetEnvironmentVariable(ServiceEnvironmentVariable.PlaywrightServiceAccessToken, null); + Environment.SetEnvironmentVariable(ServiceEnvironmentVariable.PlaywrightServiceRunId, null); + Environment.SetEnvironmentVariable(ReporterConstants.s_pLAYWRIGHT_SERVICE_REPORTING_URL, null); + } + + private static string GetToken(Dictionary claims, DateTime? expires = null) + { + var tokenHandler = new JsonWebTokenHandler(); + var token = tokenHandler.CreateToken(new SecurityTokenDescriptor + { + Claims = claims, + Expires = expires ?? DateTime.UtcNow.AddMinutes(10), + }); + return token!; + } + + [Test] + public void PlaywrightReporter_Ctor_WithNulls() + { + var reporter = new PlaywrightReporter(); + Assert.NotNull(reporter._environment); + Assert.NotNull(reporter._xmlRunSettings); + Assert.NotNull(reporter._consoleWriter); + Assert.NotNull(reporter._jsonWebTokenHandler); + Assert.NotNull(reporter._logger); + + Assert.Null(reporter._parametersDictionary); + Assert.Null(reporter._playwrightService); + Assert.Null(reporter._testProcessor); + } + + [Test] + public void InitializePlaywrightReporter_InvalidRunSettings_PrintsMessageAndExits() + { + var consoleWriterMock = new Mock(); + var environmentMock = new Mock(); + + environmentMock.Setup(e => e.Exit(It.IsAny())).Callback(i => { }); + consoleWriterMock.Setup(c => c.WriteError(It.IsAny())).Verifiable(); + + var xmlSettings = @" + + + + + +"; + var reporter = new PlaywrightReporter(logger: null, environment: environmentMock.Object, xmlRunSettings: null, consoleWriter: consoleWriterMock.Object, jsonWebTokenHandler: null); + reporter.InitializePlaywrightReporter(xmlSettings); + + consoleWriterMock.Verify(c => c.WriteError(It.IsRegex("Failed to initialize PlaywrightServiceSettings")), Times.Once); + environmentMock.Verify(e => e.Exit(1), Times.Once); + Assert.Null(reporter._testProcessor); + } + + [Test] + public void InitializePlaywrightReporter_WithNoServiceUrl_PrintsMessageAndExits() + { + var consoleWriterMock = new Mock(); + var environmentMock = new Mock(); + + environmentMock.Setup(e => e.Exit(It.IsAny())).Callback(i => { }); + consoleWriterMock.Setup(c => c.WriteError(It.IsAny())).Verifiable(); + + var reporter = new PlaywrightReporter(logger: null, environment: environmentMock.Object, xmlRunSettings: null, consoleWriter: consoleWriterMock.Object, jsonWebTokenHandler: null); + + reporter.InitializePlaywrightReporter(""); + + consoleWriterMock.Verify(c => c.WriteError(Constants.s_no_service_endpoint_error_message), Times.Once); + environmentMock.Verify(e => e.Exit(1), Times.Once); + Assert.Null(reporter._testProcessor); + } + + [Test] + public void InitializePlaywrightReporter_WithNoAccessToken_PrintsMessageAndExits() + { + var consoleWriterMock = new Mock(); + var environmentMock = new Mock(); + + environmentMock.Setup(e => e.Exit(It.IsAny())).Callback(i => { }); + environmentMock.Setup(e => e.GetEnvironmentVariable(ReporterConstants.s_pLAYWRIGHT_SERVICE_REPORTING_URL)).Returns("reporting-url"); + consoleWriterMock.Setup(c => c.WriteError(It.IsAny())).Verifiable(); + + var reporter = new PlaywrightReporter(logger: null, environment: environmentMock.Object, xmlRunSettings: null, consoleWriter: consoleWriterMock.Object, jsonWebTokenHandler: null); + + reporter.InitializePlaywrightReporter(""); + + consoleWriterMock.Verify(c => c.WriteError(Constants.s_no_auth_error), Times.Once); + environmentMock.Verify(e => e.Exit(1), Times.Once); + Assert.Null(reporter._testProcessor); + } + + [Test] + public void InitializePlaywrightReporter_Default_SetsUpTestProcessor() + { + var consoleWriterMock = new Mock(); + var environmentMock = new Mock(); + var accessToken = GetToken(new Dictionary { { "aid", "account-id-guid" }, { "oid", "org-id" }, { "id", "uuid" }, { "name", "username" } }); + + environmentMock.Setup(e => e.GetEnvironmentVariable(ServiceEnvironmentVariable.PlaywrightServiceRunId)).Returns("run-id"); + environmentMock.Setup(e => e.GetEnvironmentVariable(ReporterConstants.s_pLAYWRIGHT_SERVICE_REPORTING_URL)).Returns("https://eastus.reporting.api.playwright.microsoft.com"); + environmentMock.Setup(e => e.GetEnvironmentVariable(ServiceEnvironmentVariable.PlaywrightServiceAccessToken)).Returns(accessToken); + + var reporter = new PlaywrightReporter(logger: null, environment: environmentMock.Object, xmlRunSettings: null, consoleWriter: consoleWriterMock.Object, jsonWebTokenHandler: null); + + reporter.InitializePlaywrightReporter(""); + + Assert.NotNull(reporter._testProcessor); + Assert.Multiple(() => + { + Assert.AreEqual("run-id", reporter._testProcessor!._cloudRunMetadata.RunId!); + Assert.AreEqual("account-id-guid", reporter._testProcessor!._cloudRunMetadata.WorkspaceId!); + Assert.AreEqual(new Uri("https://eastus.reporting.api.playwright.microsoft.com"), reporter._testProcessor!._cloudRunMetadata.BaseUri!); + Assert.IsTrue(reporter._testProcessor!._cloudRunMetadata.EnableResultPublish); + Assert.IsTrue(reporter._testProcessor!._cloudRunMetadata.EnableGithubSummary); + Assert.NotNull(reporter._testProcessor!._cloudRunMetadata.TestRunStartTime); + Assert.AreEqual(1, reporter._testProcessor!._cloudRunMetadata.NumberOfTestWorkers); + Assert.AreEqual("account-id-guid", reporter._testProcessor!._cloudRunMetadata.AccessTokenDetails!.aid!); + Assert.AreEqual("org-id", reporter._testProcessor!._cloudRunMetadata.AccessTokenDetails!.oid!); + Assert.AreEqual("uuid", reporter._testProcessor!._cloudRunMetadata.AccessTokenDetails!.id!); + Assert.AreEqual("username", reporter._testProcessor!._cloudRunMetadata.AccessTokenDetails!.userName!); + }); + } + + [Test] + public void InitializePlaywrightReporter_WithGHCI_UsesCIInfoToCreateRunIdAndPopulateTestProcessor() + { + var consoleWriterMock = new Mock(); + var environmentMock = new Mock(); + var accessToken = GetToken(new Dictionary { { "aid", "account-id-guid" }, { "oid", "org-id" }, { "id", "uuid" }, { "name", "username" } }); + + environmentMock.Setup(e => e.GetEnvironmentVariable("GITHUB_ACTIONS")).Returns("true"); + environmentMock.Setup(e => e.GetEnvironmentVariable("GITHUB_RUN_ID")).Returns("run-id"); + environmentMock.Setup(e => e.GetEnvironmentVariable("GITHUB_REPOSITORY_ID")).Returns("repo-id"); + environmentMock.Setup(e => e.GetEnvironmentVariable("GITHUB_ACTOR")).Returns("actor"); + environmentMock.Setup(e => e.GetEnvironmentVariable("GITHUB_SHA")).Returns("commit-id"); + environmentMock.Setup(e => e.GetEnvironmentVariable("GITHUB_SERVER_URL")).Returns("https://github.com"); + environmentMock.Setup(e => e.GetEnvironmentVariable("GITHUB_REPOSITORY")).Returns("repo"); + environmentMock.Setup(e => e.GetEnvironmentVariable("GITHUB_RUN_ATTEMPT")).Returns("1"); + environmentMock.Setup(e => e.GetEnvironmentVariable("GITHUB_JOB")).Returns("job-id"); + environmentMock.Setup(e => e.GetEnvironmentVariable("GITHUB_REF_NAME")).Returns("branch-name"); + environmentMock.Setup(e => e.GetEnvironmentVariable(ReporterConstants.s_pLAYWRIGHT_SERVICE_REPORTING_URL)).Returns("https://eastus.reporting.api.playwright.microsoft.com"); + environmentMock.Setup(e => e.GetEnvironmentVariable(ServiceEnvironmentVariable.PlaywrightServiceAccessToken)).Returns(accessToken); + + var reporter = new PlaywrightReporter(logger: null, environment: environmentMock.Object, xmlRunSettings: null, consoleWriter: consoleWriterMock.Object, jsonWebTokenHandler: null); + + reporter.InitializePlaywrightReporter(""); + + Assert.NotNull(reporter._testProcessor); + var runId = ReporterUtils.CalculateSha1Hash($"{CIConstants.s_gITHUB_ACTIONS}-repo-id-run-id-1"); + Assert.Multiple(() => + { + Assert.AreEqual("run-id", reporter._testProcessor!._cIInfo.RunId); + Assert.AreEqual("repo-id", reporter._testProcessor!._cIInfo.Repo); + Assert.AreEqual("commit-id", reporter._testProcessor!._cIInfo.CommitId); + Assert.AreEqual("actor", reporter._testProcessor!._cIInfo.Author); + Assert.AreEqual("branch-name", reporter._testProcessor!._cIInfo.Branch); + Assert.AreEqual(CIConstants.s_gITHUB_ACTIONS, reporter._testProcessor!._cIInfo.Provider); + Assert.AreEqual("job-id", reporter._testProcessor!._cIInfo.JobId); + Assert.AreEqual(1, reporter._testProcessor!._cIInfo.RunAttempt); + Assert.AreEqual(reporter._testProcessor!._cIInfo.RevisionUrl, "https://github.com/repo/commit/commit-id"); + }); + environmentMock.Verify(e => e.SetEnvironmentVariable(ServiceEnvironmentVariable.PlaywrightServiceRunId, runId), Times.Once); + } + + [Test] + public void InitializePlaywrightReporter_WithADOCI_UsesCIInfoToCreateRunIdAndPopulateTestProcessor() + { + var consoleWriterMock = new Mock(); + var environmentMock = new Mock(); + var accessToken = GetToken(new Dictionary { { "aid", "account-id-guid" }, { "oid", "org-id" }, { "id", "uuid" }, { "name", "username" } }); + + environmentMock.Setup(e => e.GetEnvironmentVariable("AZURE_HTTP_USER_AGENT")).Returns("true"); + environmentMock.Setup(e => e.GetEnvironmentVariable("TF_BUILD")).Returns("true"); + environmentMock.Setup(e => e.GetEnvironmentVariable("BUILD_REPOSITORY_ID")).Returns("repo-id"); + environmentMock.Setup(e => e.GetEnvironmentVariable("BUILD_REQUESTEDFOR")).Returns("actor"); + environmentMock.Setup(e => e.GetEnvironmentVariable("BUILD_SOURCEVERSION")).Returns("commit-id"); + environmentMock.Setup(e => e.GetEnvironmentVariable("SYSTEM_TEAMFOUNDATIONCOLLECTIONURI")).Returns("https://ado.com/"); + environmentMock.Setup(e => e.GetEnvironmentVariable("SYSTEM_TEAMPROJECT")).Returns("project"); + environmentMock.Setup(e => e.GetEnvironmentVariable("BUILD_REPOSITORY_NAME")).Returns("repo"); + environmentMock.Setup(e => e.GetEnvironmentVariable("RELEASE_ATTEMPTNUMBER")).Returns("1"); + environmentMock.Setup(e => e.GetEnvironmentVariable("BUILD_SOURCEBRANCH")).Returns("branch-name"); + environmentMock.Setup(e => e.GetEnvironmentVariable("RELEASE_DEFINITIONID")).Returns("definition-id"); + environmentMock.Setup(e => e.GetEnvironmentVariable("RELEASE_DEPLOYMENTID")).Returns("release-id"); + environmentMock.Setup(e => e.GetEnvironmentVariable(ReporterConstants.s_pLAYWRIGHT_SERVICE_REPORTING_URL)).Returns("https://eastus.reporting.api.playwright.microsoft.com"); + environmentMock.Setup(e => e.GetEnvironmentVariable(ServiceEnvironmentVariable.PlaywrightServiceAccessToken)).Returns(accessToken); + + var reporter = new PlaywrightReporter(logger: null, environment: environmentMock.Object, xmlRunSettings: null, consoleWriter: consoleWriterMock.Object, jsonWebTokenHandler: null); + + reporter.InitializePlaywrightReporter(""); + + Assert.NotNull(reporter._testProcessor); + var runId = ReporterUtils.CalculateSha1Hash($"{CIConstants.s_aZURE_DEVOPS}-repo-id-definition-id-release-id-1"); + Assert.Multiple(() => + { + Assert.AreEqual("definition-id-release-id", reporter._testProcessor!._cIInfo.RunId); + Assert.AreEqual("repo-id", reporter._testProcessor!._cIInfo.Repo); + Assert.AreEqual("commit-id", reporter._testProcessor!._cIInfo.CommitId); + Assert.AreEqual("actor", reporter._testProcessor!._cIInfo.Author); + Assert.AreEqual("branch-name", reporter._testProcessor!._cIInfo.Branch); + Assert.AreEqual(CIConstants.s_aZURE_DEVOPS, reporter._testProcessor!._cIInfo.Provider); + Assert.AreEqual("release-id", reporter._testProcessor!._cIInfo.JobId); + Assert.AreEqual(1, reporter._testProcessor!._cIInfo.RunAttempt); + Assert.AreEqual(reporter._testProcessor!._cIInfo.RevisionUrl, "https://ado.com/project/_git/repo/commit/commit-id"); + }); + environmentMock.Verify(e => e.SetEnvironmentVariable(ServiceEnvironmentVariable.PlaywrightServiceRunId, runId), Times.Once); + } + + [Test] + public void InitializePlaywrightReporter_ParseRunSettings_SetupTestProcessor() + { + var consoleWriterMock = new Mock(); + var accessToken = GetToken(new Dictionary { { "aid", "eastus_e3d6f8f5-8c4e-4f74-a6f6-6b6d423d6d42" }, { "oid", "org-id" }, { "id", "uuid" }, { "name", "username" } }); + + Environment.SetEnvironmentVariable(ServiceEnvironmentVariable.PlaywrightServiceUri, "wss://eastus.api.playwright.microsoft.com/accounts/eastus_e3d6f8f5-8c4e-4f74-a6f6-6b6d423d6d42/browsers"); + Environment.SetEnvironmentVariable(ServiceEnvironmentVariable.PlaywrightServiceAccessToken, accessToken); + + var reporter = new PlaywrightReporter(logger: null, environment: null, xmlRunSettings: null, consoleWriter: consoleWriterMock.Object, jsonWebTokenHandler: null); + var xmlSettings = @" + + + + + + + + + 3 + + +"; + reporter.InitializePlaywrightReporter(xmlSettings); + + Assert.NotNull(reporter._testProcessor); + Assert.Multiple(() => + { + Assert.AreEqual("Sample-Run-Id", reporter._testProcessor!._cloudRunMetadata.RunId!); + Assert.AreEqual(new Uri("https://eastus.reporting.api.playwright.microsoft.com"), reporter._testProcessor!._cloudRunMetadata.BaseUri!); + Assert.IsFalse(reporter._testProcessor!._cloudRunMetadata.EnableResultPublish); + Assert.IsFalse(reporter._testProcessor!._cloudRunMetadata.EnableGithubSummary); + Assert.AreEqual(3, reporter._testProcessor!._cloudRunMetadata.NumberOfTestWorkers); + Assert.AreEqual(ServiceAuthType.AccessToken, reporter._playwrightService!.ServiceAuth); + }); + } + } +} diff --git a/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/tests/Processor/DataProcessorTests.cs b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/tests/Processor/DataProcessorTests.cs index ebf5745770256..2964243098888 100644 --- a/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/tests/Processor/DataProcessorTests.cs +++ b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/tests/Processor/DataProcessorTests.cs @@ -23,7 +23,8 @@ public void GetTestRun_ReturnsTestRunDto() { oid = "oid", userName = " userName " - } + }, + NumberOfTestWorkers = 5 }; var cIInfo = new CIInfo { @@ -54,7 +55,7 @@ public void GetTestRun_ReturnsTestRunDto() Assert.AreEqual(cIInfo.RevisionUrl, result.CiConfig!.RevisionUrl); Assert.AreEqual(cIInfo.Provider, result.CiConfig!.CiProviderName); Assert.IsNotNull(result.TestRunConfig); - Assert.AreEqual(1, result.TestRunConfig!.Workers); + Assert.AreEqual(5, result.TestRunConfig!.Workers); Assert.AreEqual("1.40", result.TestRunConfig!.PwVersion); Assert.AreEqual(60000, result.TestRunConfig!.Timeout); Assert.AreEqual("WebTest", result.TestRunConfig!.TestType); @@ -72,6 +73,7 @@ public void GetTestRun_ReturnsTestRunDto() public void GetTestRunShard_ReturnsTestRunShardDto() { var cloudRunMetadata = new CloudRunMetadata(); + cloudRunMetadata.NumberOfTestWorkers = 6; var cIInfo = new CIInfo(); var dataProcessor = new DataProcessor(cloudRunMetadata, cIInfo); @@ -84,7 +86,7 @@ public void GetTestRunShard_ReturnsTestRunShardDto() Assert.IsNotNull(result.Summary); Assert.AreEqual("RUNNING", result.Summary!.Status); Assert.IsNotNull(result.Summary!.StartTime); - Assert.AreEqual(1, result.Workers); + Assert.AreEqual(6, result.Workers); } [Test] From 869cf9064a64307d27292e5f6466086d60b51368 Mon Sep 17 00:00:00 2001 From: Siddharth Singha Roy Date: Tue, 12 Nov 2024 00:46:21 +0530 Subject: [PATCH 2/2] chore(): update api spec --- ...loper.MicrosoftPlaywrightTesting.TestLogger.netstandard2.0.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/api/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.netstandard2.0.cs b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/api/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.netstandard2.0.cs index b961eccd0a9bb..4c4c2fb4de3f2 100644 --- a/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/api/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.netstandard2.0.cs +++ b/sdk/playwrighttesting/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger/api/Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.netstandard2.0.cs @@ -29,6 +29,7 @@ public partial class RunSettingKey public static readonly string EnableResultPublish; public static readonly string ExposeNetwork; public static readonly string ManagedIdentityClientId; + public static readonly string NumberOfTestWorkers; public static readonly string Os; public static readonly string RunId; public static readonly string ServiceAuthType;