Skip to content

Commit

Permalink
Merge pull request #132 from Lombiq/issue/OSOE-47
Browse files Browse the repository at this point in the history
OSOE-47: Add VerifyElementTexts extension, interface for PageNavigationState, EnableApplicationInsightsOfflineOperation() extension method
  • Loading branch information
Piedone authored Feb 21, 2022
2 parents 8ec373e + f111cf2 commit 0555731
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 17 deletions.
3 changes: 3 additions & 0 deletions Lombiq.Tests.UI.Samples/Lombiq.Tests.UI.Samples.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<!-- Eliminates problem with dotnet publish caused by duplicate .htmlvalidate.json file. See
https://docs.microsoft.com/en-us/dotnet/core/compatibility/sdk/6.0/duplicate-files-in-output. -->
<ErrorOnDuplicatePublishOutputFiles>false</ErrorOnDuplicatePublishOutputFiles>
</PropertyGroup>

<ItemGroup>
Expand Down
24 changes: 8 additions & 16 deletions Lombiq.Tests.UI.Samples/UITestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,22 +63,14 @@ protected override Task ExecuteTestAsync(
configuration.BrowserConfiguration.Headless =
TestConfigurationManager.GetBoolConfiguration("BrowserConfiguration:Headless", defaultValue: false);
// There are event handlers that you can hook into. This is just one but check out the others in
// OrchardCoreConfiguration if you're interested.
configuration.OrchardCoreConfiguration.BeforeAppStart +=
(_, argumentsBuilder) =>
{
// This is quite handy! We're adding a configuration parameter when launching the app. This
// can be used to set configuration for configuration providers, see the docs:
// https://docs.orchardcore.net/en/latest/docs/reference/core/Configuration/.
// What's happening here is that we set the Lombiq Application Insights module's parameter
// to allow us to test it. We'll get back to this later when writing the actual test.
argumentsBuilder
.Add("--OrchardCore:Lombiq_Hosting_Azure_ApplicationInsights:EnableOfflineOperation")
.Add("true");
return Task.CompletedTask;
};
// There are event handlers that you can hook into. This method sets BeforeAppStart which is just
// one of many. Check out the others in OrchardCoreConfiguration if you're interested.
// This is quite handy! We're adding a configuration parameter when launching the app. This
// can be used to set configuration for configuration providers, see the docs:
// https://docs.orchardcore.net/en/latest/docs/reference/core/Configuration/.
// What's happening here is that we set the Lombiq Application Insights module's parameter
// to allow us to test it. We'll get back to this later when writing the actual test.
configuration.OrchardCoreConfiguration.EnableApplicationInsightsOfflineOperation();
// Note that automatic HTML markup validation is enabled on every page change by default (you can
// disable it with the below config). With this, you can make sure that the HTML markup the app
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
using OpenQA.Selenium.Remote;
using Shouldly;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;

namespace Lombiq.Tests.UI.Extensions
{
Expand Down Expand Up @@ -101,6 +103,36 @@ public static void ErrorMessageExists(this UITestContext context, string errorMe
.Text
.ShouldBe(errorMessage);

/// <summary>
/// Retrieves the elements according to <paramref name="by"/> and matches their text content against <paramref
/// name="toMatch"/>. Both the text contents and <paramref name="toMatch"/> strings are trimmed. If an item in
/// <paramref name="toMatch"/> is <see langword="null" /> it's ignored among the result elements too. Every
/// other item is converted to string, using invariant culture where possible.
/// </summary>
public static void VerifyElementTexts(this UITestContext context, By by, params object[] toMatch)
{
context.Exists(by); // Ensure content is loaded first.

var dontCare = toMatch
.Select((item, index) => item == null ? index : -1)
.Where(index => index >= 0)
.ToList();
var target = toMatch
.Select(item => item == null ? null : FormattableString.Invariant($"{item}"))
.Select(item => item?.Trim())
.ToArray();

context
.GetAll(by)
.Select((element, index) => dontCare.Contains(index) ? null : element.Text.Trim())
.ToArray()
.ShouldBe(target);
}

/// <inheritdoc cref="VerifyElementTexts(UITestContext, By, object[])"/>
public static void VerifyElementTexts(this UITestContext context, By by, IEnumerable<object> toMatch) =>
VerifyElementTexts(context, by, toMatch is object[] array ? array : toMatch.ToArray());

private static ExtendedSearchContext<RemoteWebDriver> CreateSearchContext(this UITestContext context) =>
new(
context.Driver,
Expand Down
22 changes: 22 additions & 0 deletions Lombiq.Tests.UI/Models/IWebContentState.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System;

namespace Lombiq.Tests.UI.Models
{
/// <summary>
/// Represents a state of some web content that may change, for example via page navigation or dynamic content after
/// user interaction.
/// </summary>
public interface IWebContentState
{
/// <summary>
/// Returns <see langword="true"/> if navigation has occurred or the content has changed based on some
/// previously provided content.
/// </summary>
bool CheckIfNavigationHasOccurred();

/// <summary>
/// Waits until <see cref="CheckIfNavigationHasOccurred"/> evaluates to <see langword="true"/>.
/// </summary>
public void Wait(TimeSpan? timeout = null, TimeSpan? interval = null);
}
}
7 changes: 6 additions & 1 deletion Lombiq.Tests.UI/Models/PageNavigationState.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
using Lombiq.Tests.UI.Extensions;
using Lombiq.Tests.UI.Helpers;
using Lombiq.Tests.UI.Services;
using OpenQA.Selenium;
using System;

namespace Lombiq.Tests.UI.Models
{
/// <summary>
/// Represents the current web page in terms of whether the browser has navigated away from it yet.
/// </summary>
public class PageNavigationState
public class PageNavigationState : IWebContentState
{
private readonly IWebElement _root;

Expand All @@ -31,5 +33,8 @@ public bool CheckIfNavigationHasOccurred()
return true;
}
}

public void Wait(TimeSpan? timeout = null, TimeSpan? interval = null) =>
ReliabilityHelper.DoWithRetriesOrFail(CheckIfNavigationHasOccurred, timeout, interval);
}
}
16 changes: 16 additions & 0 deletions Lombiq.Tests.UI/Services/OrchardCoreInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,22 @@ public class OrchardCoreConfiguration
public string SnapshotDirectoryPath { get; set; }
public BeforeAppStartHandler BeforeAppStart { get; set; }
public BeforeTakeSnapshotHandler BeforeTakeSnapshot { get; set; }

/// <summary>
/// Adds a command line argument to the app during <see cref="BeforeAppStart"/> that switches AI into offline
/// mode. This way it won't try to reach out to a remote server with telemetry and the test remains
/// self-sufficient.
/// </summary>
public void EnableApplicationInsightsOfflineOperation() =>
BeforeAppStart +=
(_, argumentsBuilder) =>
{
argumentsBuilder
.Add("--OrchardCore:Lombiq_Hosting_Azure_ApplicationInsights:EnableOfflineOperation")
.Add("true");
return Task.CompletedTask;
};
}

/// <summary>
Expand Down

0 comments on commit 0555731

Please sign in to comment.