HTML tag.
+ var pageTitle = "Test page";
+
+ var contentItemsPage = await context.GoToContentItemsPageAsync();
+ context.RefreshCurrentAtataContext();
+ contentItemsPage
+ .CreateNewPage()
+ .Title.Set(pageTitle)
+ .Publish.ClickAndGo()
+ .AlertMessages.Should.Contain(message => message.IsSuccess)
+ .Items[item => item.Title == pageTitle].View.Click();
+
+ var page = new OrdinaryPage(pageTitle);
+ context.Scope.AtataContext.Go.ToNextWindow(page)
+ .AggregateAssert(page => page
+ .PageTitle.Should.Contain(pageTitle));
+
+ context.Driver.Exists(By.XPath($"//div[contains(text(), '" + pageTitle + "')]").Visible());
+
+ page.CloseWindow();
+
+ await context.TestTurningFeatureOnAndOffAsync();
+ await context.TestLogoutAsync();
+ },
+ browser,
+ configuration =>
+ {
+ configuration.AccessibilityCheckingConfiguration.AxeBuilderConfigurator += axeBuilder =>
+ AccessibilityCheckingConfiguration
+ .ConfigureWcag21aa(axeBuilder)
+ .DisableRules("color-contrast");
+
+ return Task.CompletedTask;
+ });
+ }
+}
diff --git a/test/OrchardCore.Tests.UI/Tests/AzureBlobStorageTests.cs b/test/OrchardCore.Tests.UI/Tests/AzureBlobStorageTests.cs
new file mode 100644
index 00000000000..8e5ba1b2a81
--- /dev/null
+++ b/test/OrchardCore.Tests.UI/Tests/AzureBlobStorageTests.cs
@@ -0,0 +1,43 @@
+using System.Threading.Tasks;
+using Lombiq.Tests.UI.Attributes;
+using Lombiq.Tests.UI.Extensions;
+using Lombiq.Tests.UI.Pages;
+using Lombiq.Tests.UI.Services;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace OrchardCore.Tests.UI.Tests
+{
+ public class AzureBlobStorageTests : UITestBase
+ {
+ public AzureBlobStorageTests(ITestOutputHelper testOutputHelper)
+ : base(testOutputHelper)
+ {
+ }
+
+ [Theory, Chrome]
+ public Task BasicOrchardFeaturesShouldWorkWithBlogAndAzureBlobStorage(Browser browser) =>
+ ExecuteTestAsync(
+ async context =>
+ {
+ await context.TestSetupAsync(new OrchardCoreSetupParameters(context)
+ {
+ RecipeId = "Blog.Tests",
+ }.ConfigureDatabaseSettings(context));
+
+ await context.TestBasicOrchardFeaturesExceptSetupAsync();
+ },
+ browser,
+ configuration =>
+ {
+ configuration.UseAzureBlobStorage = true;
+
+ configuration.AccessibilityCheckingConfiguration.AxeBuilderConfigurator += axeBuilder =>
+ AccessibilityCheckingConfiguration
+ .ConfigureWcag21aa(axeBuilder)
+ .DisableRules("color-contrast");
+
+ return Task.CompletedTask;
+ });
+ }
+}
diff --git a/test/OrchardCore.Tests.UI/Tests/BlankRecipeTests.cs b/test/OrchardCore.Tests.UI/Tests/BlankRecipeTests.cs
new file mode 100644
index 00000000000..61dade3bf1d
--- /dev/null
+++ b/test/OrchardCore.Tests.UI/Tests/BlankRecipeTests.cs
@@ -0,0 +1,56 @@
+using System.Linq;
+using System.Threading.Tasks;
+using Lombiq.Tests.UI.Attributes;
+using Lombiq.Tests.UI.Extensions;
+using Lombiq.Tests.UI.Pages;
+using Lombiq.Tests.UI.Services;
+using OpenQA.Selenium;
+using Shouldly;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace OrchardCore.Tests.UI.Tests
+{
+ public class BlankRecipeTests : UITestBase
+ {
+ public BlankRecipeTests(ITestOutputHelper testOutputHelper)
+ : base(testOutputHelper)
+ {
+ }
+
+ [Theory, Chrome]
+ public Task BasicOrchardFeaturesShouldWorkWithBlank(Browser browser) =>
+ ExecuteTestAsync(
+ async context =>
+ {
+ await context.TestSetupAsync(new OrchardCoreSetupParameters(context)
+ {
+ RecipeId = "Blank.Tests",
+ }.ConfigureDatabaseSettings(context));
+
+ await context.TestLoginWithInvalidDataAsync();
+ await context.TestLoginAsync();
+ await context.TestTurningFeatureOnAndOffAsync();
+ await context.TestLogoutAsync();
+ },
+ browser,
+ configuration =>
+ {
+ configuration.HtmlValidationConfiguration.RunHtmlValidationAssertionOnAllPageChanges = false;
+ configuration.AccessibilityCheckingConfiguration.RunAccessibilityCheckingAssertionOnAllPageChanges = false;
+
+ configuration.AssertBrowserLog = logEntries =>
+ logEntries.ShouldNotContain(
+ logEntry => IsValidBrowserLogEntry(logEntry),
+ logEntries.Where(IsValidBrowserLogEntry).ToFormattedString());
+
+ return Task.CompletedTask;
+ });
+
+ private static bool IsValidBrowserLogEntry(LogEntry logEntry)
+ {
+ return OrchardCoreUITestExecutorConfiguration.IsValidBrowserLogEntry(logEntry) &&
+ !logEntry.IsNotFoundLogEntry("/");
+ }
+ }
+}
diff --git a/test/OrchardCore.Tests.UI/Tests/BlogRecipeTests.cs b/test/OrchardCore.Tests.UI/Tests/BlogRecipeTests.cs
new file mode 100644
index 00000000000..24a346a3da0
--- /dev/null
+++ b/test/OrchardCore.Tests.UI/Tests/BlogRecipeTests.cs
@@ -0,0 +1,48 @@
+using System.Threading.Tasks;
+using Lombiq.Tests.UI.Attributes;
+using Lombiq.Tests.UI.Extensions;
+using Lombiq.Tests.UI.Pages;
+using Lombiq.Tests.UI.Services;
+using OpenQA.Selenium;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace OrchardCore.Tests.UI.Tests
+{
+ public class BlogRecipeTests : UITestBase
+ {
+ public BlogRecipeTests(ITestOutputHelper testOutputHelper)
+ : base(testOutputHelper)
+ {
+ }
+
+ [Theory, Chrome]
+ public Task BasicOrchardFeaturesShouldWorkWithBlog(Browser browser) =>
+ ExecuteTestAsync(
+ async context =>
+ {
+ await context.TestSetupAsync(new OrchardCoreSetupParameters(context)
+ {
+ RecipeId = "Blog.Tests",
+ }.ConfigureDatabaseSettings(context));
+
+ await context.TestBasicOrchardFeaturesExceptSetupAsync();
+ },
+ browser,
+ configuration =>
+ {
+ configuration.AccessibilityCheckingConfiguration.AxeBuilderConfigurator += axeBuilder =>
+ AccessibilityCheckingConfiguration
+ .ConfigureWcag21aa(axeBuilder)
+ .DisableRules("color-contrast");
+
+ return Task.CompletedTask;
+ });
+
+ [Theory(Skip = "Used to test artifact creation during build."), Chrome]
+ public Task IntentionallyFailingTest(Browser browser) =>
+ ExecuteTestAfterSetupAsync(
+ context => context.Exists(By.Id("navbarasdfds")),
+ browser);
+ }
+}
diff --git a/test/OrchardCore.Tests.UI/Tests/ComingSoonRecipeTests.cs b/test/OrchardCore.Tests.UI/Tests/ComingSoonRecipeTests.cs
new file mode 100644
index 00000000000..12f76caa987
--- /dev/null
+++ b/test/OrchardCore.Tests.UI/Tests/ComingSoonRecipeTests.cs
@@ -0,0 +1,44 @@
+using System.Threading.Tasks;
+using Lombiq.Tests.UI.Attributes;
+using Lombiq.Tests.UI.Extensions;
+using Lombiq.Tests.UI.Pages;
+using Lombiq.Tests.UI.Services;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace OrchardCore.Tests.UI.Tests
+{
+ public class ComingSoonRecipeTests : UITestBase
+ {
+ public ComingSoonRecipeTests(ITestOutputHelper testOutputHelper)
+ : base(testOutputHelper)
+ {
+ }
+
+ [Theory, Chrome]
+ public Task BasicOrchardFeaturesShouldWorkWithComingSoon(Browser browser) =>
+ ExecuteTestAsync(
+ async context =>
+ {
+ await context.TestSetupAsync(new OrchardCoreSetupParameters(context)
+ {
+ RecipeId = "ComingSoon.Tests",
+ }.ConfigureDatabaseSettings(context));
+
+ await context.TestRegistrationWithInvalidDataAsync();
+ await context.TestRegistrationAsync();
+ await context.TestRegistrationWithAlreadyRegisteredEmailAsync();
+ await context.TestLoginWithInvalidDataAsync();
+ await context.TestLoginAsync();
+ await context.TestTurningFeatureOnAndOffAsync();
+ await context.TestLogoutAsync();
+ },
+ browser,
+ configuration =>
+ {
+ // Axe crashes the WebDriver on the second page load for some reason.
+ configuration.AccessibilityCheckingConfiguration.RunAccessibilityCheckingAssertionOnAllPageChanges = false;
+ return Task.CompletedTask;
+ });
+ }
+}
diff --git a/test/OrchardCore.Tests.UI/Tests/HeadlessRecipeTests.cs b/test/OrchardCore.Tests.UI/Tests/HeadlessRecipeTests.cs
new file mode 100644
index 00000000000..eee1cc02ef7
--- /dev/null
+++ b/test/OrchardCore.Tests.UI/Tests/HeadlessRecipeTests.cs
@@ -0,0 +1,41 @@
+using System.Threading.Tasks;
+using Lombiq.Tests.UI.Attributes;
+using Lombiq.Tests.UI.Extensions;
+using Lombiq.Tests.UI.Pages;
+using Lombiq.Tests.UI.Services;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace OrchardCore.Tests.UI.Tests
+{
+ public class HeadlessRecipeTests : UITestBase
+ {
+ public HeadlessRecipeTests(ITestOutputHelper testOutputHelper)
+ : base(testOutputHelper)
+ {
+ }
+
+ [Theory, Chrome]
+ public Task BasicOrchardFeaturesShouldWorkWithHeadless(Browser browser) =>
+ ExecuteTestAsync(
+ async context =>
+ {
+ await context.TestSetupAsync(new OrchardCoreSetupParameters(context)
+ {
+ RecipeId = "Headless.Tests",
+ }.ConfigureDatabaseSettings(context));
+
+ await context.TestLoginWithInvalidDataAsync();
+ await context.TestLoginAsync();
+ await context.TestTurningFeatureOnAndOffAsync();
+ await context.TestLogoutAsync();
+ },
+ browser,
+ configuration =>
+ {
+ configuration.HtmlValidationConfiguration.RunHtmlValidationAssertionOnAllPageChanges = false;
+ configuration.AccessibilityCheckingConfiguration.RunAccessibilityCheckingAssertionOnAllPageChanges = false;
+ return Task.CompletedTask;
+ });
+ }
+}
diff --git a/test/OrchardCore.Tests.UI/Tests/InvalidSetupTests.cs b/test/OrchardCore.Tests.UI/Tests/InvalidSetupTests.cs
new file mode 100644
index 00000000000..27254739c95
--- /dev/null
+++ b/test/OrchardCore.Tests.UI/Tests/InvalidSetupTests.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Threading.Tasks;
+using Lombiq.Tests.UI.Attributes;
+using Lombiq.Tests.UI.Extensions;
+using Lombiq.Tests.UI.Pages;
+using Lombiq.Tests.UI.Services;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace OrchardCore.Tests.UI.Tests
+{
+ public class InvalidSetupTests : UITestBase
+ {
+ public InvalidSetupTests(ITestOutputHelper testOutputHelper)
+ : base(testOutputHelper)
+ {
+ }
+
+ [Theory, Chrome]
+ public Task SetupWithInvalidDataShouldFail(Browser browser) =>
+ ExecuteTestAsync(
+ context => context.TestSetupWithInvalidDataAsync(
+ new OrchardCoreSetupParameters(context)
+ {
+ SiteName = String.Empty,
+ UserName = String.Empty,
+ Email = String.Empty,
+ Password = String.Empty,
+ }.ConfigureDatabaseSettings(context)),
+ browser);
+ }
+}
+
diff --git a/test/OrchardCore.Tests.UI/Tests/SaaSRecipeTests.cs b/test/OrchardCore.Tests.UI/Tests/SaaSRecipeTests.cs
new file mode 100644
index 00000000000..3cfa04a29ec
--- /dev/null
+++ b/test/OrchardCore.Tests.UI/Tests/SaaSRecipeTests.cs
@@ -0,0 +1,79 @@
+using System.Threading.Tasks;
+using Lombiq.Tests.UI.Attributes;
+using Lombiq.Tests.UI.Extensions;
+using Lombiq.Tests.UI.Pages;
+using Lombiq.Tests.UI.Services;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace OrchardCore.Tests.UI.Tests
+{
+ public class SaaSRecipeTests : UITestBase
+ {
+ public SaaSRecipeTests(ITestOutputHelper testOutputHelper)
+ : base(testOutputHelper)
+ {
+ }
+
+ [Theory, Chrome]
+ public Task BasicOrchardFeaturesShouldWorkWithSaaS(Browser browser) =>
+ ExecuteTestAsync(
+ async context =>
+ {
+ await context.TestSetupAsync(new OrchardCoreSetupParameters(context)
+ {
+ RecipeId = "SaaS.Tests",
+ }.ConfigureDatabaseSettings(context));
+
+ await context.TestRegistrationWithInvalidDataAsync();
+ await context.TestRegistrationAsync();
+ await context.TestRegistrationWithAlreadyRegisteredEmailAsync();
+ await context.TestLoginWithInvalidDataAsync();
+ await context.TestLoginAsync();
+ await context.TestTurningFeatureOnAndOffAsync();
+ await context.TestLogoutAsync();
+ },
+ browser);
+
+ [Theory, Chrome]
+ public Task BasicOrchardFeaturesShouldWorkWithNewTenant(Browser browser) =>
+ ExecuteTestAsync(
+ async context =>
+ {
+ await context.GoToSetupPageAndSetupOrchardCoreAsync(
+ new OrchardCoreSetupParameters(context)
+ {
+ SiteName = "Orchard Core - UI Testing",
+ RecipeId = "SaaS.Tests",
+ SiteTimeZoneValue = "America/New_York",
+ }.ConfigureDatabaseSettings(context));
+
+ await context.SignInDirectlyAsync();
+
+ await context.CreateAndSwitchToTenantManuallyAsync("test", "test");
+
+ var tenantSetupParameters = new OrchardCoreSetupParameters(context)
+ {
+ SiteName = "Test Tenant",
+ RecipeId = "Blog.Tests",
+ RunSetupOnCurrentPage = true,
+ }.ConfigureDatabaseSettings(context);
+
+ tenantSetupParameters.TablePrefix += "t2";
+
+ await context.GoToSetupPageAndSetupOrchardCoreAsync(tenantSetupParameters);
+
+ await context.TestBasicOrchardFeaturesExceptSetupAsync();
+ },
+ browser,
+ configuration =>
+ {
+ configuration.AccessibilityCheckingConfiguration.AxeBuilderConfigurator += axeBuilder =>
+ AccessibilityCheckingConfiguration
+ .ConfigureWcag21aa(axeBuilder)
+ .DisableRules("color-contrast");
+
+ return Task.CompletedTask;
+ });
+ }
+}
diff --git a/test/OrchardCore.Tests.UI/UITestBase.cs b/test/OrchardCore.Tests.UI/UITestBase.cs
new file mode 100644
index 00000000000..9c9e32943f6
--- /dev/null
+++ b/test/OrchardCore.Tests.UI/UITestBase.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Threading.Tasks;
+using Lombiq.Tests.UI;
+using Lombiq.Tests.UI.Pages;
+using Lombiq.Tests.UI.Services;
+using OrchardCore.Tests.UI.Helpers;
+using Xunit.Abstractions;
+
+namespace OrchardCore.Tests.UI
+{
+ public class UITestBase : OrchardCoreUITestBase
+ {
+ protected UITestBase(ITestOutputHelper testOutputHelper)
+ : base(testOutputHelper)
+ {
+ }
+
+ protected override Task ExecuteTestAfterSetupAsync(
+ Func testAsync,
+ Browser browser,
+ Func changeConfigurationAsync)
+ {
+ throw new NotSupportedException(
+ "Since these tests are run for all database engines supported by Orchard Core, and setup snapshotting " +
+ "required by this method is only supported for SQLite and SQL Server by the UI Testing Toolbox, this " +
+ "isn't supported. Run the applicable setup operation in the test instead.");
+ }
+
+ protected override Task ExecuteTestAsync(
+ Func testAsync,
+ Browser browser,
+ Func> setupOperation,
+ Func changeConfigurationAsync) =>
+ base.ExecuteTestAsync(
+ testAsync,
+ browser,
+ setupOperation,
+ async configuration =>
+ {
+ configuration.AccessibilityCheckingConfiguration.RunAccessibilityCheckingAssertionOnAllPageChanges = true;
+
+ configuration.UseSqlServer =
+ DatabaseProviderHelper.GetCIDatabaseProvider() == OrchardCoreSetupPage.DatabaseType.SqlServer;
+
+ if (configuration.UseSqlServer)
+ {
+ configuration.SqlServerDatabaseConfiguration.ConnectionStringTemplate =
+ configuration.SqlServerDatabaseConfiguration.ConnectionStringTemplate +
+ ";Encrypt=False;TrustServerCertificate=True";
+ }
+
+ if (changeConfigurationAsync != null) await changeConfigurationAsync(configuration);
+ });
+ }
+}
diff --git a/test/OrchardCore.Tests.UI/xunit.runner.json b/test/OrchardCore.Tests.UI/xunit.runner.json
new file mode 100644
index 00000000000..100b12679c4
--- /dev/null
+++ b/test/OrchardCore.Tests.UI/xunit.runner.json
@@ -0,0 +1,6 @@
+{
+ "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json",
+ "parallelizeAssembly": false,
+ "parallelizeTestCollections": true,
+ "maxParallelThreads": 0
+}