diff --git a/visual-dotnet/SauceLabs.Visual.Tests/VisualApiTest.cs b/visual-dotnet/SauceLabs.Visual.Tests/VisualApiTest.cs index 9c3ee3a1..33090797 100644 --- a/visual-dotnet/SauceLabs.Visual.Tests/VisualApiTest.cs +++ b/visual-dotnet/SauceLabs.Visual.Tests/VisualApiTest.cs @@ -3,7 +3,6 @@ using System.Net.Http; using System.Text; using System.Threading.Tasks; -using Newtonsoft.Json; using NUnit.Framework; using RichardSzalay.MockHttp; using SauceLabs.Visual.GraphQL; diff --git a/visual-dotnet/SauceLabs.Visual/GraphQL/CreateSnapshotFromWebDriverIn.cs b/visual-dotnet/SauceLabs.Visual/GraphQL/CreateSnapshotFromWebDriverIn.cs index dd2ce82d..912e11f7 100644 --- a/visual-dotnet/SauceLabs.Visual/GraphQL/CreateSnapshotFromWebDriverIn.cs +++ b/visual-dotnet/SauceLabs.Visual/GraphQL/CreateSnapshotFromWebDriverIn.cs @@ -38,7 +38,9 @@ public CreateSnapshotFromWebDriverIn( DiffingMethod diffingMethod, RegionIn[] regions, bool captureDom, - string? clipSelector + string? clipSelector, + string? suiteName, + string? testName ) { BuildUuid = buildUuid; @@ -50,6 +52,8 @@ public CreateSnapshotFromWebDriverIn( SessionId = sessionId; CaptureDom = captureDom; ClipSelector = clipSelector; + SuiteName = suiteName; + TestName = testName; } } } \ No newline at end of file diff --git a/visual-dotnet/SauceLabs.Visual/Utils/GraphQLResponseExtension.cs b/visual-dotnet/SauceLabs.Visual/Utils/GraphQLResponseExtension.cs index 19773292..e528a337 100644 --- a/visual-dotnet/SauceLabs.Visual/Utils/GraphQLResponseExtension.cs +++ b/visual-dotnet/SauceLabs.Visual/Utils/GraphQLResponseExtension.cs @@ -3,7 +3,7 @@ namespace SauceLabs.Visual.Utils { - public static class GraphQLResponseExtension + internal static class GraphQLResponseExtension { public static T EnsureValidResponse(this GraphQLResponse response) { diff --git a/visual-dotnet/SauceLabs.Visual/Utils/StringUtils.cs b/visual-dotnet/SauceLabs.Visual/Utils/StringUtils.cs index beadc8a8..64ca4cf0 100644 --- a/visual-dotnet/SauceLabs.Visual/Utils/StringUtils.cs +++ b/visual-dotnet/SauceLabs.Visual/Utils/StringUtils.cs @@ -1,6 +1,6 @@ namespace SauceLabs.Visual.Utils { - public static class StringUtils + internal static class StringUtils { /// /// IsNullOrEmpty checks that the string null, empty or contains only whitespaces. diff --git a/visual-dotnet/SauceLabs.Visual/VisualCheckOptions.cs b/visual-dotnet/SauceLabs.Visual/VisualCheckOptions.cs index 988d8bb2..cd2e8993 100644 --- a/visual-dotnet/SauceLabs.Visual/VisualCheckOptions.cs +++ b/visual-dotnet/SauceLabs.Visual/VisualCheckOptions.cs @@ -1,3 +1,5 @@ +using System.Diagnostics; +using System.Linq; using OpenQA.Selenium; using SauceLabs.Visual.Models; @@ -14,5 +16,29 @@ public class VisualCheckOptions public IWebElement[]? IgnoreElements { get; set; } public bool? CaptureDom { get; set; } public string? ClipSelector { get; set; } + + /// + /// SuiteName manually set the SuiteName of the Test. + /// + public string? SuiteName { get; set; } + /// + /// TestName manually set the TestName of the Test. + /// + public string? TestName { get; set; } + + private bool HasIncompleteTestContext() => string.IsNullOrEmpty(SuiteName) || string.IsNullOrEmpty(TestName); + + internal void EnsureTestContextIsPopulated(string callerMemberName, string? previousSuiteName) + { + if (string.IsNullOrEmpty(callerMemberName) || HasIncompleteTestContext()) + { + return; + } + + var stack = new StackTrace(); + var frame = stack.GetFrames()?.FirstOrDefault(f => f.GetMethod().Name == callerMemberName); + SuiteName ??= frame?.GetMethod().DeclaringType?.FullName ?? previousSuiteName; + TestName ??= callerMemberName; + } } } \ No newline at end of file diff --git a/visual-dotnet/SauceLabs.Visual/VisualClient.cs b/visual-dotnet/SauceLabs.Visual/VisualClient.cs index 9b74b018..7606aa5f 100644 --- a/visual-dotnet/SauceLabs.Visual/VisualClient.cs +++ b/visual-dotnet/SauceLabs.Visual/VisualClient.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; using System.Threading.Tasks; using OpenQA.Selenium; using Polly; @@ -26,6 +27,8 @@ public class VisualClient : IDisposable public bool CaptureDom { get; set; } = false; private readonly ResiliencePipeline _retryPipeline; + private string? _previousSuiteName = null; + /// /// Creates a new instance of VisualClient /// @@ -220,22 +223,33 @@ private async Task FinishBuild(VisualBuild build) /// the name of the screenshot /// the configuration for the screenshot capture and comparison /// - public async Task VisualCheck(string name, VisualCheckOptions? options = null) + public Task VisualCheck(string name, VisualCheckOptions? options = null, + [CallerMemberName] string callerMemberName = "") + { + options ??= new VisualCheckOptions(); + options.EnsureTestContextIsPopulated(callerMemberName, _previousSuiteName); + _previousSuiteName = options.SuiteName; + return VisualCheckAsync(name, options); + } + + private async Task VisualCheckAsync(string name, VisualCheckOptions options) { var ignored = new List(); - ignored.AddRange(options?.IgnoreRegions?.Select(r => new RegionIn(r)) ?? new List()); - ignored.AddRange(options?.IgnoreElements?.Select(r => new RegionIn(r)) ?? new List()); + ignored.AddRange(options.IgnoreRegions?.Select(r => new RegionIn(r)) ?? new List()); + ignored.AddRange(options.IgnoreElements?.Select(r => new RegionIn(r)) ?? new List()); var result = (await _api.CreateSnapshotFromWebDriver(new CreateSnapshotFromWebDriverIn( buildUuid: Build.Id, name: name, jobId: _jobId, - diffingMethod: options?.DiffingMethod ?? DiffingMethod.Simple, + diffingMethod: options.DiffingMethod ?? DiffingMethod.Simple, regions: ignored.ToArray(), sessionId: _sessionId, sessionMetadata: _sessionMetadataBlob ?? "", - captureDom: options?.CaptureDom ?? CaptureDom, - clipSelector: options?.ClipSelector + captureDom: options.CaptureDom ?? CaptureDom, + clipSelector: options.ClipSelector, + suiteName: options.SuiteName, + testName: options.TestName ))).EnsureValidResponse(); result.Result.Diffs.Nodes.ToList().ForEach(d => _screenshotIds.Add(d.Id)); return result.Result.Id;