From 35134d4ba97b971296d9ba4a2eab74d7c532f2b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1vid=20El-Saig?= Date: Fri, 28 Jul 2023 16:14:59 +0200 Subject: [PATCH 01/10] Add status accessor and controller. --- .../Controllers/InteractiveModeController.cs | 26 +++++++++++++++++++ .../IInteractiveModeStatusAccessor.cs | 12 +++++++++ .../Services/InteractiveModeStatusAccessor.cs | 6 +++++ Lombiq.Tests.UI.Shortcuts/Startup.cs | 6 ++++- 4 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 Lombiq.Tests.UI.Shortcuts/Controllers/InteractiveModeController.cs create mode 100644 Lombiq.Tests.UI.Shortcuts/Services/IInteractiveModeStatusAccessor.cs create mode 100644 Lombiq.Tests.UI.Shortcuts/Services/InteractiveModeStatusAccessor.cs diff --git a/Lombiq.Tests.UI.Shortcuts/Controllers/InteractiveModeController.cs b/Lombiq.Tests.UI.Shortcuts/Controllers/InteractiveModeController.cs new file mode 100644 index 000000000..f764cbf21 --- /dev/null +++ b/Lombiq.Tests.UI.Shortcuts/Controllers/InteractiveModeController.cs @@ -0,0 +1,26 @@ +using Lombiq.Tests.UI.Shortcuts.Services; +using Microsoft.AspNetCore.Mvc; + +namespace Lombiq.Tests.UI.Shortcuts.Controllers; + +public class InteractiveModeController : Controller +{ + private readonly IInteractiveModeStatusAccessor _interactiveModeStatusAccessor; + + public InteractiveModeController(IInteractiveModeStatusAccessor interactiveModeStatusAccessor) => + _interactiveModeStatusAccessor = interactiveModeStatusAccessor; + + public IActionResult Index() + { + _interactiveModeStatusAccessor.Enabled = true; + return View(); + } + + public IActionResult Status() => Json(_interactiveModeStatusAccessor); + + public IActionResult Continue() + { + _interactiveModeStatusAccessor.Enabled = false; + return Ok(); + } +} diff --git a/Lombiq.Tests.UI.Shortcuts/Services/IInteractiveModeStatusAccessor.cs b/Lombiq.Tests.UI.Shortcuts/Services/IInteractiveModeStatusAccessor.cs new file mode 100644 index 000000000..30d785566 --- /dev/null +++ b/Lombiq.Tests.UI.Shortcuts/Services/IInteractiveModeStatusAccessor.cs @@ -0,0 +1,12 @@ +namespace Lombiq.Tests.UI.Shortcuts.Services; + +/// +/// A container for the flag indicating if interactive mode is enabled. +/// +public interface IInteractiveModeStatusAccessor +{ + /// + /// Gets or sets a value indicating whether interactive mode is enabled. + /// + bool Enabled { get; set; } +} diff --git a/Lombiq.Tests.UI.Shortcuts/Services/InteractiveModeStatusAccessor.cs b/Lombiq.Tests.UI.Shortcuts/Services/InteractiveModeStatusAccessor.cs new file mode 100644 index 000000000..bef3d15a2 --- /dev/null +++ b/Lombiq.Tests.UI.Shortcuts/Services/InteractiveModeStatusAccessor.cs @@ -0,0 +1,6 @@ +namespace Lombiq.Tests.UI.Shortcuts.Services; + +public class InteractiveModeStatusAccessor : IInteractiveModeStatusAccessor +{ + public bool Enabled { get; set; } +} diff --git a/Lombiq.Tests.UI.Shortcuts/Startup.cs b/Lombiq.Tests.UI.Shortcuts/Startup.cs index c72469217..6dd5a9d0e 100644 --- a/Lombiq.Tests.UI.Shortcuts/Startup.cs +++ b/Lombiq.Tests.UI.Shortcuts/Startup.cs @@ -7,6 +7,10 @@ namespace Lombiq.Tests.UI.Shortcuts; public class Startup : StartupBase { - public override void ConfigureServices(IServiceCollection services) => + public override void ConfigureServices(IServiceCollection services) + { + services.AddSingleton(); + services.Configure((options) => options.Filters.Add(typeof(ApplicationInfoInjectingFilter))); + } } From 126a2d33ea8d8ba555125862a771c1437e5aafb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1vid=20El-Saig?= Date: Fri, 28 Jul 2023 16:15:05 +0200 Subject: [PATCH 02/10] Add view. --- .../Views/InteractiveMode/Index.cshtml | 32 +++++++++++++++++++ .../Views/_ViewImports.cshtml | 12 +++++++ 2 files changed, 44 insertions(+) create mode 100644 Lombiq.Tests.UI.Shortcuts/Views/InteractiveMode/Index.cshtml create mode 100644 Lombiq.Tests.UI.Shortcuts/Views/_ViewImports.cshtml diff --git a/Lombiq.Tests.UI.Shortcuts/Views/InteractiveMode/Index.cshtml b/Lombiq.Tests.UI.Shortcuts/Views/InteractiveMode/Index.cshtml new file mode 100644 index 000000000..6e35f8955 --- /dev/null +++ b/Lombiq.Tests.UI.Shortcuts/Views/InteractiveMode/Index.cshtml @@ -0,0 +1,32 @@ + + +
+
+

@T["Interactive Mode"]

+

@T["If you see this, your code has evoked the context.SwitchToInteractiveAsync() method. This stops the test evaluation and waits until you click the button below."]

+ + @T["Continue Test"] + +
+
\ No newline at end of file diff --git a/Lombiq.Tests.UI.Shortcuts/Views/_ViewImports.cshtml b/Lombiq.Tests.UI.Shortcuts/Views/_ViewImports.cshtml new file mode 100644 index 000000000..be43650df --- /dev/null +++ b/Lombiq.Tests.UI.Shortcuts/Views/_ViewImports.cshtml @@ -0,0 +1,12 @@ +@inherits OrchardCore.DisplayManagement.Razor.RazorPage + +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers +@addTagHelper *, OrchardCore.Contents.TagHelpers +@addTagHelper *, OrchardCore.DisplayManagement +@addTagHelper *, OrchardCore.ResourceManagement + +@using Lombiq.Tests.UI.Shortcuts.Controllers +@using Microsoft.AspNetCore.Mvc.Localization +@using Newtonsoft.Json +@using Newtonsoft.Json.Serialization +@using OrchardCore.Mvc.Core.Utilities From 4b0fc15c675da1c88f4b4d7393e77452124af11f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1vid=20El-Saig?= Date: Fri, 28 Jul 2023 22:23:38 +0200 Subject: [PATCH 03/10] Add SwitchToInteractiveAsync. --- .../Controllers/InteractiveModeController.cs | 7 +++- .../Views/InteractiveMode/Index.cshtml | 8 ++-- .../ShortcutsUITestContextExtensions.cs | 41 +++++++++++++++++++ 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/Lombiq.Tests.UI.Shortcuts/Controllers/InteractiveModeController.cs b/Lombiq.Tests.UI.Shortcuts/Controllers/InteractiveModeController.cs index f764cbf21..308b62a80 100644 --- a/Lombiq.Tests.UI.Shortcuts/Controllers/InteractiveModeController.cs +++ b/Lombiq.Tests.UI.Shortcuts/Controllers/InteractiveModeController.cs @@ -1,8 +1,11 @@ +using Lombiq.HelpfulLibraries.AspNetCore.Mvc; using Lombiq.Tests.UI.Shortcuts.Services; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace Lombiq.Tests.UI.Shortcuts.Controllers; +[DevelopmentAndLocalhostOnly] public class InteractiveModeController : Controller { private readonly IInteractiveModeStatusAccessor _interactiveModeStatusAccessor; @@ -16,7 +19,9 @@ public IActionResult Index() return View(); } - public IActionResult Status() => Json(_interactiveModeStatusAccessor); + [AllowAnonymous] + [Route("api/InteractiveMode/IsInteractive")] + public IActionResult IsInteractive() => Json(_interactiveModeStatusAccessor.Enabled); public IActionResult Continue() { diff --git a/Lombiq.Tests.UI.Shortcuts/Views/InteractiveMode/Index.cshtml b/Lombiq.Tests.UI.Shortcuts/Views/InteractiveMode/Index.cshtml index 6e35f8955..a9e813e8a 100644 --- a/Lombiq.Tests.UI.Shortcuts/Views/InteractiveMode/Index.cshtml +++ b/Lombiq.Tests.UI.Shortcuts/Views/InteractiveMode/Index.cshtml @@ -23,9 +23,11 @@

@T["Interactive Mode"]

-

@T["If you see this, your code has evoked the context.SwitchToInteractiveAsync() method. This stops the test evaluation and waits until you click the button below."]

- +

+ @T["If you see this, your code has evoked the context.SwitchToInteractiveAsync() method."] + @T["This stops the test evaluation and waits until you click the button below."] +

+
@T["Continue Test"]
diff --git a/Lombiq.Tests.UI/Extensions/ShortcutsUITestContextExtensions.cs b/Lombiq.Tests.UI/Extensions/ShortcutsUITestContextExtensions.cs index 2d72b642e..013258bce 100644 --- a/Lombiq.Tests.UI/Extensions/ShortcutsUITestContextExtensions.cs +++ b/Lombiq.Tests.UI/Extensions/ShortcutsUITestContextExtensions.cs @@ -434,6 +434,12 @@ public interface IShortcutsApi /// [Get("/api/ApplicationInfo")] Task GetApplicationInfoFromApiAsync(); + + /// + /// Sends a web request to endpoint. + /// + [Get("api/InteractiveMode/IsInteractive")] + Task IsInteractiveModeEnabledAsync(); } /// @@ -584,6 +590,41 @@ await UsingScopeAsync( return eventUrl; } + /// + /// Opens a new tab with the + /// page. Visiting this page enables the interactive mode flag so it can be awaited with the extension method. + /// + public static Task EnterInteractiveModeAsync(this UITestContext context) + { + context.Driver.SwitchTo().NewWindow(WindowType.Tab); + context.Driver.SwitchTo().Window(context.Driver.WindowHandles[^1]); + + return context.GoToAsync(controller => controller.Index()); + } + + /// + /// Periodically polls the and waits half a second if it's + /// . + /// + public static async Task WaitInteractiveModeAsync(this UITestContext context) + { + var client = context.GetApi(); + while (await client.IsInteractiveModeEnabledAsync()) + { + await Task.Delay(TimeSpan.FromMilliseconds(500)); + } + } + + public static async Task SwitchToInteractiveAsync(this UITestContext context) + { + await context.EnterInteractiveModeAsync(); + await context.WaitInteractiveModeAsync(); + + context.ExecuteScript("window.close();"); + context.SwitchToLastWindow(); + } + private static bool IsAdminTheme(IManifestInfo manifest) => manifest.Tags.Any(tag => tag.EqualsOrdinalIgnoreCase(ManifestConstants.AdminTag)); From 330a5ef00bb4d79ad61124ad39d28c7636a305ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1vid=20El-Saig?= Date: Fri, 28 Jul 2023 23:16:15 +0200 Subject: [PATCH 04/10] Add ui test. --- .../Tests/InteractiveModeTests.cs | 42 +++++++++++++++++++ .../Controllers/InteractiveModeController.cs | 2 +- 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 Lombiq.Tests.UI.Samples/Tests/InteractiveModeTests.cs diff --git a/Lombiq.Tests.UI.Samples/Tests/InteractiveModeTests.cs b/Lombiq.Tests.UI.Samples/Tests/InteractiveModeTests.cs new file mode 100644 index 000000000..4b0b43e72 --- /dev/null +++ b/Lombiq.Tests.UI.Samples/Tests/InteractiveModeTests.cs @@ -0,0 +1,42 @@ +using Lombiq.Tests.UI.Attributes; +using Lombiq.Tests.UI.Extensions; +using Lombiq.Tests.UI.Services; +using OpenQA.Selenium; +using Shouldly; +using System.Threading.Tasks; +using Xunit; +using Xunit.Abstractions; + +namespace Lombiq.Tests.UI.Samples.Tests; + +public class InteractiveModeTests : UITestBase +{ + public InteractiveModeTests(ITestOutputHelper testOutputHelper) + : base(testOutputHelper) + { + } + + [Theory, Chrome] + public Task EnteringInteractiveModeShouldWait(Browser browser) => + ExecuteTestAfterSetupAsync( + async context => + { + await context.GoToHomePageAsync(); + var currentUrl = context.Driver.Url; + + await Task.WhenAll( + context.SwitchToInteractiveAsync(), + Task.Run(async () => + { + // Ensure that the interactive mode polls for status at least once, so the arbitrary waiting + // actually works in a real testing scenario. + await Task.Delay(1000); + + await context.ClickReliablyOnAsync(By.ClassName("interactive__continue")); + })); + + // Ensure that the info tab is closed and the control handed back to the last tab. + context.Driver.Url.ShouldBe(currentUrl); + }, + browser); +} diff --git a/Lombiq.Tests.UI.Shortcuts/Controllers/InteractiveModeController.cs b/Lombiq.Tests.UI.Shortcuts/Controllers/InteractiveModeController.cs index 308b62a80..d748c28cd 100644 --- a/Lombiq.Tests.UI.Shortcuts/Controllers/InteractiveModeController.cs +++ b/Lombiq.Tests.UI.Shortcuts/Controllers/InteractiveModeController.cs @@ -5,6 +5,7 @@ namespace Lombiq.Tests.UI.Shortcuts.Controllers; +[AllowAnonymous] [DevelopmentAndLocalhostOnly] public class InteractiveModeController : Controller { @@ -19,7 +20,6 @@ public IActionResult Index() return View(); } - [AllowAnonymous] [Route("api/InteractiveMode/IsInteractive")] public IActionResult IsInteractive() => Json(_interactiveModeStatusAccessor.Enabled); From f81cd6391f9355efacb467f6c598b2e460fc3f89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1vid=20El-Saig?= Date: Sat, 29 Jul 2023 07:35:11 +0200 Subject: [PATCH 05/10] different phrasing --- Lombiq.Tests.UI.Shortcuts/Views/InteractiveMode/Index.cshtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lombiq.Tests.UI.Shortcuts/Views/InteractiveMode/Index.cshtml b/Lombiq.Tests.UI.Shortcuts/Views/InteractiveMode/Index.cshtml index a9e813e8a..72c49f638 100644 --- a/Lombiq.Tests.UI.Shortcuts/Views/InteractiveMode/Index.cshtml +++ b/Lombiq.Tests.UI.Shortcuts/Views/InteractiveMode/Index.cshtml @@ -24,7 +24,7 @@

@T["Interactive Mode"]

- @T["If you see this, your code has evoked the context.SwitchToInteractiveAsync() method."] + @T["If you see this, your code has called the context.SwitchToInteractiveAsync() method."] @T["This stops the test evaluation and waits until you click the button below."]

From c69efce9d80ac871263c7783703e06dea7bd06df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1vid=20El-Saig?= Date: Sat, 29 Jul 2023 07:39:51 +0200 Subject: [PATCH 06/10] Fix API path. --- Lombiq.Tests.UI.Samples/Tests/InteractiveModeTests.cs | 1 - Lombiq.Tests.UI/Extensions/ShortcutsUITestContextExtensions.cs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Lombiq.Tests.UI.Samples/Tests/InteractiveModeTests.cs b/Lombiq.Tests.UI.Samples/Tests/InteractiveModeTests.cs index 4b0b43e72..5d5e1fcf4 100644 --- a/Lombiq.Tests.UI.Samples/Tests/InteractiveModeTests.cs +++ b/Lombiq.Tests.UI.Samples/Tests/InteractiveModeTests.cs @@ -21,7 +21,6 @@ public Task EnteringInteractiveModeShouldWait(Browser browser) => ExecuteTestAfterSetupAsync( async context => { - await context.GoToHomePageAsync(); var currentUrl = context.Driver.Url; await Task.WhenAll( diff --git a/Lombiq.Tests.UI/Extensions/ShortcutsUITestContextExtensions.cs b/Lombiq.Tests.UI/Extensions/ShortcutsUITestContextExtensions.cs index 013258bce..d660c0482 100644 --- a/Lombiq.Tests.UI/Extensions/ShortcutsUITestContextExtensions.cs +++ b/Lombiq.Tests.UI/Extensions/ShortcutsUITestContextExtensions.cs @@ -438,7 +438,7 @@ public interface IShortcutsApi /// /// Sends a web request to endpoint. /// - [Get("api/InteractiveMode/IsInteractive")] + [Get("/api/InteractiveMode/IsInteractive")] Task IsInteractiveModeEnabledAsync(); } From fcbc8719ec435909503e58d98ed185ec6009727d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1vid=20El-Saig?= Date: Sat, 29 Jul 2023 08:02:49 +0200 Subject: [PATCH 07/10] Fix tab closing. --- Lombiq.Tests.UI/Extensions/ShortcutsUITestContextExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lombiq.Tests.UI/Extensions/ShortcutsUITestContextExtensions.cs b/Lombiq.Tests.UI/Extensions/ShortcutsUITestContextExtensions.cs index d660c0482..3d09bb55b 100644 --- a/Lombiq.Tests.UI/Extensions/ShortcutsUITestContextExtensions.cs +++ b/Lombiq.Tests.UI/Extensions/ShortcutsUITestContextExtensions.cs @@ -621,7 +621,7 @@ public static async Task SwitchToInteractiveAsync(this UITestContext context) await context.EnterInteractiveModeAsync(); await context.WaitInteractiveModeAsync(); - context.ExecuteScript("window.close();"); + context.Driver.Close(); context.SwitchToLastWindow(); } From 8953ad7abd741d8879396ed4a06e1d97f5565071 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1vid=20El-Saig?= Date: Sat, 29 Jul 2023 08:53:47 +0200 Subject: [PATCH 08/10] Added sample with comments. --- .../Tests/InteractiveModeTests.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Lombiq.Tests.UI.Samples/Tests/InteractiveModeTests.cs b/Lombiq.Tests.UI.Samples/Tests/InteractiveModeTests.cs index 5d5e1fcf4..3d98e50a4 100644 --- a/Lombiq.Tests.UI.Samples/Tests/InteractiveModeTests.cs +++ b/Lombiq.Tests.UI.Samples/Tests/InteractiveModeTests.cs @@ -3,6 +3,7 @@ using Lombiq.Tests.UI.Services; using OpenQA.Selenium; using Shouldly; +using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; @@ -16,6 +17,28 @@ public InteractiveModeTests(ITestOutputHelper testOutputHelper) { } + [Theory(Skip = "Use this to test to try out the interactive mode. This is not a real test you can run in CI."), Chrome] + [SuppressMessage("Usage", "xUnit1004:Test methods should not be skipped", Justification = "Only a demo.")] + public Task SampleTest(Browser browser) => + ExecuteTestAfterSetupAsync( + async context => + { + await context.SignInDirectlyAsync(); + + // One use-case of interactive mode is to look around in the admin dashboard and troubleshoot the + // current settings without programmatically navigating there. + await context.SignInDirectlyAndGoToDashboardAsync(); + await context.SwitchToInteractiveAsync(); + + // Afterwards if you can still evaluate code as normal so `SignInDirectlyAndGoToDashboardAsync()` can be + // inserted anywhere. Bare in mind, that it's safest to use it before code that's already going to + // navigate away, like `GetCurrentUserNameAsync()` here. This ensures any manual navigation you did + // won't affect the test. If that's not practical, you can also do your thing in a new tab and close it + // before continuing the test. + (await context.GetCurrentUserNameAsync()).ShouldNotBeNullOrWhiteSpace(); + }, + browser); + [Theory, Chrome] public Task EnteringInteractiveModeShouldWait(Browser browser) => ExecuteTestAfterSetupAsync( From 1d1c791aa866a2ee0a51dee42cd2178b6b0feb6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1vid=20El-Saig?= Date: Sat, 29 Jul 2023 16:33:42 +0200 Subject: [PATCH 09/10] Add code documentation to InteractiveModeTests. --- Lombiq.Tests.UI.Samples/Readme.md | 1 + Lombiq.Tests.UI.Samples/Tests/InteractiveModeTests.cs | 11 +++++++++++ Lombiq.Tests.UI.Samples/Tests/TenantTests.cs | 1 + 3 files changed, 13 insertions(+) diff --git a/Lombiq.Tests.UI.Samples/Readme.md b/Lombiq.Tests.UI.Samples/Readme.md index 101457d95..15a4ac422 100644 --- a/Lombiq.Tests.UI.Samples/Readme.md +++ b/Lombiq.Tests.UI.Samples/Readme.md @@ -26,6 +26,7 @@ For general details about and on using the Toolbox see the [root Readme](../Read - [Database snapshot tests](Tests/DatabaseSnapshotTests.cs) - [Basic visual verification tests](Tests/BasicVisualVerificationTests.cs) - [Testing in tenants](Tests/TenantTests.cs) +- [Interactive mode](Tests/InteractiveModeTests.cs) ## Adding new tutorials diff --git a/Lombiq.Tests.UI.Samples/Tests/InteractiveModeTests.cs b/Lombiq.Tests.UI.Samples/Tests/InteractiveModeTests.cs index 3d98e50a4..77aa1c092 100644 --- a/Lombiq.Tests.UI.Samples/Tests/InteractiveModeTests.cs +++ b/Lombiq.Tests.UI.Samples/Tests/InteractiveModeTests.cs @@ -10,6 +10,11 @@ namespace Lombiq.Tests.UI.Samples.Tests; +// Sometimes you want to debug the test session and assuming direct control would be nice. But you can't just drop a +// breakpoint in the test, since the Orchard Core webapp and the test are the same process so it would pause both. The +// `context.SwitchToInteractiveAsync()` extension method opens a new tab with info about the interactive mode and then +// causes the test thread to wait until you've clicked on the "Continue Test" button in this tab. During that time you +// can interact with OC as if it was a normal execution. public class InteractiveModeTests : UITestBase { public InteractiveModeTests(ITestOutputHelper testOutputHelper) @@ -17,6 +22,7 @@ public InteractiveModeTests(ITestOutputHelper testOutputHelper) { } + // If you want to try it out yourself, just remove the "Skip" parameter and run this test. [Theory(Skip = "Use this to test to try out the interactive mode. This is not a real test you can run in CI."), Chrome] [SuppressMessage("Usage", "xUnit1004:Test methods should not be skipped", Justification = "Only a demo.")] public Task SampleTest(Browser browser) => @@ -39,6 +45,9 @@ public Task SampleTest(Browser browser) => }, browser); + // This test checks if interactive mode works by opening it in one thread, and then clicking it away in a different + // thread. This ensures that the new tab correctly appears with the clickable "Continue Test" button, and then + // disappears once it's clicked. [Theory, Chrome] public Task EnteringInteractiveModeShouldWait(Browser browser) => ExecuteTestAfterSetupAsync( @@ -62,3 +71,5 @@ await Task.WhenAll( }, browser); } + +// END OF TRAINING SECTION: Interactive mode. diff --git a/Lombiq.Tests.UI.Samples/Tests/TenantTests.cs b/Lombiq.Tests.UI.Samples/Tests/TenantTests.cs index 613f7e533..437425401 100644 --- a/Lombiq.Tests.UI.Samples/Tests/TenantTests.cs +++ b/Lombiq.Tests.UI.Samples/Tests/TenantTests.cs @@ -63,3 +63,4 @@ await context.CreateAndSwitchToTenantAsync( } // END OF TRAINING SECTION: Testing in tenants. +// NEXT STATION: Head over to InteractiveModeTests.cs. From 8378dd31d4be6245e71a4841b17173e45437f3dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1vid=20El-Saig?= Date: Sat, 29 Jul 2023 16:40:27 +0200 Subject: [PATCH 10/10] Mention in the readme. --- Lombiq.Tests.UI.Samples/Tests/InteractiveModeTests.cs | 1 + Readme.md | 1 + 2 files changed, 2 insertions(+) diff --git a/Lombiq.Tests.UI.Samples/Tests/InteractiveModeTests.cs b/Lombiq.Tests.UI.Samples/Tests/InteractiveModeTests.cs index 77aa1c092..bba0b7399 100644 --- a/Lombiq.Tests.UI.Samples/Tests/InteractiveModeTests.cs +++ b/Lombiq.Tests.UI.Samples/Tests/InteractiveModeTests.cs @@ -15,6 +15,7 @@ namespace Lombiq.Tests.UI.Samples.Tests; // `context.SwitchToInteractiveAsync()` extension method opens a new tab with info about the interactive mode and then // causes the test thread to wait until you've clicked on the "Continue Test" button in this tab. During that time you // can interact with OC as if it was a normal execution. +// Note: this extension depends on Lombiq.Tests.UI.Shortcuts being enabled in your OC app. public class InteractiveModeTests : UITestBase { public InteractiveModeTests(ITestOutputHelper testOutputHelper) diff --git a/Readme.md b/Readme.md index 7e2dbfe07..93b68580a 100644 --- a/Readme.md +++ b/Readme.md @@ -25,6 +25,7 @@ Highlights: - Support for [TeamCity test metadata reporting](https://www.jetbrains.com/help/teamcity/reporting-test-metadata.html) so you can see the important details and metrics of a test at a glance in a TeamCity CI/CD server. - Visual verification testing: You can make the test fail if the look of the app changes. Demo video [here](https://www.youtube.com/watch?v=a-1zKjxTKkk). - If your app uses a camera, a fake video capture source in Chrome is supported. [Here's a demo video of the feature](https://www.youtube.com/watch?v=sGcD0eJ2ytc), and check out the docs [here](Lombiq.Tests.UI/Docs/FakeVideoCaptureSource.md). +- Interactive mode for debugging the app while the test is paused. [Here's a demo of the feature](Lombiq.Tests.UI.Samples/Tests/InteractiveModeTests.cs). See a demo video of the project [here](https://www.youtube.com/watch?v=mEUg6-pad-E), and the Orchard Harvest 2023 conference talk about automated QA in Orchard Core [here](https://youtu.be/CHdhwD2NHBU). Also, see our [Testing Toolbox](https://github.com/Lombiq/Testing-Toolbox) for similar features for lower-level tests.