From 8fa9a5478dfccd53293660bae75bebb242c81b5f Mon Sep 17 00:00:00 2001 From: "dependencyupdates[bot]" <218638057+dependencyupdates[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 09:33:40 +0000 Subject: [PATCH 1/5] Update dependency Particular.PlatformSample.ServicePulse to 2.11.0 --- src/Particular.PlatformSample/Particular.PlatformSample.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Particular.PlatformSample/Particular.PlatformSample.csproj b/src/Particular.PlatformSample/Particular.PlatformSample.csproj index d0175ee..baaa62e 100644 --- a/src/Particular.PlatformSample/Particular.PlatformSample.csproj +++ b/src/Particular.PlatformSample/Particular.PlatformSample.csproj @@ -11,7 +11,7 @@ - + From 9f12fde2d440c42d9678802eaa6532c072cf074d Mon Sep 17 00:00:00 2001 From: Jo Palac Date: Tue, 8 Sep 2026 10:39:55 +1000 Subject: [PATCH 2/5] Fix tests to make them less flaky --- .../VisualTests.cs | 79 ++++++++++++++++--- 1 file changed, 70 insertions(+), 9 deletions(-) diff --git a/src/Particular.PlatformSample.Tests/VisualTests.cs b/src/Particular.PlatformSample.Tests/VisualTests.cs index 32b9cbe..b888394 100644 --- a/src/Particular.PlatformSample.Tests/VisualTests.cs +++ b/src/Particular.PlatformSample.Tests/VisualTests.cs @@ -1,6 +1,7 @@ namespace Particular.PlatformSample.Tests; using System; +using System.Diagnostics; using System.IO; using System.Linq; using System.Threading; @@ -74,28 +75,88 @@ public async Task TearDown() [Test] public async Task ShouldBeConnected() { - await Task.Delay(2000); driver.Navigate().GoToUrl($"http://localhost:{TestPortsInternal.ServicePulse}/#/dashboard"); - await Task.Delay(10_000); + + await WaitUntil( + () => IsDocumentReady() && + driver.FindElements(By.CssSelector(".connection-failed")).Count == 0, + timeout: TimeSpan.FromSeconds(30), + failureMessage: "Expected ServicePulse to show a successful connection state on the dashboard."); var connectionFailedSpans = driver.FindElements(By.CssSelector(".connection-failed")); Assert.That(connectionFailedSpans.Count, Is.EqualTo(0)); + } + + bool IsDocumentReady() + { + if (driver is not IJavaScriptExecutor js) + { + return false; + } - var connectionOkSpans = driver.FindElements(By.CssSelector(".pa-connection-success")); - Assert.That(connectionOkSpans.Count, Is.EqualTo(2)); + var readyState = js.ExecuteScript("return document.readyState")?.ToString(); + return string.Equals(readyState, "complete", StringComparison.OrdinalIgnoreCase); } [Test] public async Task CheckMonitoringPage() { - await Task.Delay(2000); driver.Navigate().GoToUrl($"http://localhost:{TestPortsInternal.ServicePulse}/#/monitoring"); - await Task.Delay(10_000); - var primaryButtons = driver.FindElements(By.CssSelector(".btn.btn-primary")); - var noEndpointsButton = primaryButtons.Where(b => b.Text.Contains("how to enable endpoint monitoring")).FirstOrDefault(); + await WaitUntil( + () => FindMetricsHelpLink() != null, + timeout: TimeSpan.FromSeconds(30), + failureMessage: "Expected monitoring page to render a link to metrics setup guidance."); + + var noEndpointsButton = FindMetricsHelpLink(); Assert.That(noEndpointsButton, Is.Not.Null); - Assert.That(noEndpointsButton.GetAttribute("href"), Is.EqualTo("https://docs.particular.net/monitoring/metrics/")); + var href = noEndpointsButton.GetAttribute("href") ?? string.Empty; + Assert.That(href, Does.Contain("monitoring/metrics")); + } + + IWebElement FindMetricsHelpLink() + { + var primaryButtons = driver.FindElements(By.CssSelector("a.btn.btn-primary, .btn.btn-primary[href]")); + + return primaryButtons.FirstOrDefault(b => + { + var text = (b.Text ?? string.Empty).ToLowerInvariant(); + var href = (b.GetAttribute("href") ?? string.Empty).ToLowerInvariant(); + + return href.Contains("monitoring/metrics") || + (text.Contains("enable") && text.Contains("monitoring")) || + text.Contains("metrics"); + }); + } + + static async Task WaitUntil(Func condition, TimeSpan timeout, string failureMessage) + { + var sw = Stopwatch.StartNew(); + Exception lastException = null; + + while (sw.Elapsed < timeout) + { + try + { + if (condition()) + { + return; + } + } + catch (Exception ex) when (ex is WebDriverException or InvalidOperationException) + { + lastException = ex; + } + + await Task.Delay(250); + } + + if (lastException != null) + { + throw new AssertionException($"{failureMessage} Last error: {lastException.Message}"); + } + + throw new AssertionException(failureMessage); } } From ceebf48016475c177a475170e3a61c58b818482c Mon Sep 17 00:00:00 2001 From: Jo Palac Date: Tue, 8 Sep 2026 10:44:23 +1000 Subject: [PATCH 3/5] fix cancellation token --- src/Particular.PlatformSample.Tests/VisualTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Particular.PlatformSample.Tests/VisualTests.cs b/src/Particular.PlatformSample.Tests/VisualTests.cs index b888394..483d623 100644 --- a/src/Particular.PlatformSample.Tests/VisualTests.cs +++ b/src/Particular.PlatformSample.Tests/VisualTests.cs @@ -81,7 +81,7 @@ await WaitUntil( () => IsDocumentReady() && driver.FindElements(By.CssSelector(".connection-failed")).Count == 0, timeout: TimeSpan.FromSeconds(30), - failureMessage: "Expected ServicePulse to show a successful connection state on the dashboard."); + failureMessage: "Expected ServicePulse to show a successful connection state on the dashboard.", CancellationToken.None); var connectionFailedSpans = driver.FindElements(By.CssSelector(".connection-failed")); Assert.That(connectionFailedSpans.Count, Is.EqualTo(0)); @@ -106,7 +106,7 @@ public async Task CheckMonitoringPage() await WaitUntil( () => FindMetricsHelpLink() != null, timeout: TimeSpan.FromSeconds(30), - failureMessage: "Expected monitoring page to render a link to metrics setup guidance."); + failureMessage: "Expected monitoring page to render a link to metrics setup guidance.", CancellationToken.None); var noEndpointsButton = FindMetricsHelpLink(); @@ -130,7 +130,7 @@ IWebElement FindMetricsHelpLink() }); } - static async Task WaitUntil(Func condition, TimeSpan timeout, string failureMessage) + static async Task WaitUntil(Func condition, TimeSpan timeout, string failureMessage, CancellationToken cancellationToken) { var sw = Stopwatch.StartNew(); Exception lastException = null; @@ -149,7 +149,7 @@ static async Task WaitUntil(Func condition, TimeSpan timeout, string failu lastException = ex; } - await Task.Delay(250); + await Task.Delay(250,cancellationToken); } if (lastException != null) From 8221fce3a1a29bf367136464a9e10f201dda4d45 Mon Sep 17 00:00:00 2001 From: Rhys Bevilaqua Date: Tue, 8 Sep 2026 08:58:26 +0800 Subject: [PATCH 4/5] Fix formatting --- src/Particular.PlatformSample.Tests/VisualTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Particular.PlatformSample.Tests/VisualTests.cs b/src/Particular.PlatformSample.Tests/VisualTests.cs index 483d623..daa0ea5 100644 --- a/src/Particular.PlatformSample.Tests/VisualTests.cs +++ b/src/Particular.PlatformSample.Tests/VisualTests.cs @@ -149,7 +149,7 @@ static async Task WaitUntil(Func condition, TimeSpan timeout, string failu lastException = ex; } - await Task.Delay(250,cancellationToken); + await Task.Delay(250, cancellationToken); } if (lastException != null) From 5a5a25b80fa81d0d9bcc008c676e1ba5b7075393 Mon Sep 17 00:00:00 2001 From: Jo Palac Date: Tue, 8 Sep 2026 10:59:12 +1000 Subject: [PATCH 5/5] formatting fix --- src/Particular.PlatformSample.Tests/VisualTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Particular.PlatformSample.Tests/VisualTests.cs b/src/Particular.PlatformSample.Tests/VisualTests.cs index 483d623..daa0ea5 100644 --- a/src/Particular.PlatformSample.Tests/VisualTests.cs +++ b/src/Particular.PlatformSample.Tests/VisualTests.cs @@ -149,7 +149,7 @@ static async Task WaitUntil(Func condition, TimeSpan timeout, string failu lastException = ex; } - await Task.Delay(250,cancellationToken); + await Task.Delay(250, cancellationToken); } if (lastException != null)