-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
OSOE-634: Add interactive mode for debugging in Lombiq.UITestingToolbox
- Loading branch information
Showing
11 changed files
with
220 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
using Lombiq.Tests.UI.Attributes; | ||
using Lombiq.Tests.UI.Extensions; | ||
using Lombiq.Tests.UI.Services; | ||
using OpenQA.Selenium; | ||
using Shouldly; | ||
using System.Diagnostics.CodeAnalysis; | ||
using System.Threading.Tasks; | ||
using Xunit; | ||
using Xunit.Abstractions; | ||
|
||
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. | ||
// Note: this extension depends on Lombiq.Tests.UI.Shortcuts being enabled in your OC app. | ||
public class InteractiveModeTests : UITestBase | ||
{ | ||
public InteractiveModeTests(ITestOutputHelper testOutputHelper) | ||
: base(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) => | ||
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); | ||
|
||
// 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( | ||
async context => | ||
{ | ||
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); | ||
} | ||
|
||
// END OF TRAINING SECTION: Interactive mode. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
Lombiq.Tests.UI.Shortcuts/Controllers/InteractiveModeController.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
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; | ||
|
||
[AllowAnonymous] | ||
[DevelopmentAndLocalhostOnly] | ||
public class InteractiveModeController : Controller | ||
{ | ||
private readonly IInteractiveModeStatusAccessor _interactiveModeStatusAccessor; | ||
|
||
public InteractiveModeController(IInteractiveModeStatusAccessor interactiveModeStatusAccessor) => | ||
_interactiveModeStatusAccessor = interactiveModeStatusAccessor; | ||
|
||
public IActionResult Index() | ||
{ | ||
_interactiveModeStatusAccessor.Enabled = true; | ||
return View(); | ||
} | ||
|
||
[Route("api/InteractiveMode/IsInteractive")] | ||
public IActionResult IsInteractive() => Json(_interactiveModeStatusAccessor.Enabled); | ||
|
||
public IActionResult Continue() | ||
{ | ||
_interactiveModeStatusAccessor.Enabled = false; | ||
return Ok(); | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
Lombiq.Tests.UI.Shortcuts/Services/IInteractiveModeStatusAccessor.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
namespace Lombiq.Tests.UI.Shortcuts.Services; | ||
|
||
/// <summary> | ||
/// A container for the flag indicating if interactive mode is enabled. | ||
/// </summary> | ||
public interface IInteractiveModeStatusAccessor | ||
{ | ||
/// <summary> | ||
/// Gets or sets a value indicating whether interactive mode is enabled. | ||
/// </summary> | ||
bool Enabled { get; set; } | ||
} |
6 changes: 6 additions & 0 deletions
6
Lombiq.Tests.UI.Shortcuts/Services/InteractiveModeStatusAccessor.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
namespace Lombiq.Tests.UI.Shortcuts.Services; | ||
|
||
public class InteractiveModeStatusAccessor : IInteractiveModeStatusAccessor | ||
{ | ||
public bool Enabled { get; set; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
Lombiq.Tests.UI.Shortcuts/Views/InteractiveMode/Index.cshtml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
<style at="Head"> | ||
.interactive__container { | ||
position: fixed; | ||
top: 0; | ||
left: 0; | ||
width: 100vw; | ||
height: 100vh; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
background: white; | ||
z-index: 9999999; | ||
} | ||
.interactive { | ||
border: 1px solid black; | ||
padding: 2rem; | ||
width: 30vw; | ||
text-align: center; | ||
} | ||
</style> | ||
|
||
<div class="interactive__container"> | ||
<div class="interactive"> | ||
<h2>@T["Interactive Mode"]</h2> | ||
<p> | ||
@T["If you see this, your code has called the <code>context.SwitchToInteractiveAsync()</code> method."] | ||
@T["This stops the test evaluation and waits until you click the button below."] | ||
</p> | ||
<a href="@Url.Action(nameof(InteractiveModeController.Continue))" class="interactive__continue btn btn-primary"> | ||
@T["Continue Test"] | ||
</a> | ||
</div> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
@inherits OrchardCore.DisplayManagement.Razor.RazorPage<TModel> | ||
|
||
@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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters