Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/OrchardCore.Mvc.Web/OrchardCore.Mvc.Web.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

<ItemGroup>
<ProjectReference Include="..\OrchardCore\OrchardCore.Application.Mvc.Targets\OrchardCore.Application.Mvc.Targets.csproj" />
<ProjectReference Include="..\OrchardCore.Modules\OrchardCore.HealthChecks\OrchardCore.HealthChecks.csproj" />
<ProjectReference Include="..\OrchardCore.Modules\OrchardCore.Mvc.HelloWorld\OrchardCore.Mvc.HelloWorld.csproj" />
</ItemGroup>

Expand Down
41 changes: 40 additions & 1 deletion test/OrchardCore.Tests.Functional/Helpers/OrchardTestServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ public static async Task<OrchardTestServer> StartMvcAsync(string contentRoot, st

builder.Services
.AddOrchardCore()
.AddTenantFeatures("OrchardCore.HealthChecks")
.AddMvc();

ConfigureServices(builder, appDataPath, instanceId: null, loggerProvider);
Expand All @@ -104,7 +105,13 @@ public static async Task<OrchardTestServer> StartMvcAsync(string contentRoot, st

await app.StartAsync();

return new OrchardTestServer(app, GetListeningAddress(app), loggerProvider.Collector);
var address = GetListeningAddress(app);

// The OrchardCore tenant pipeline initializes lazily on the first request.
// Warm up the app now so tests don't race against pipeline initialization.
await WarmUpAsync(address);

return new OrchardTestServer(app, address, loggerProvider.Collector);
}

public void AssertNoLoggedIssues()
Expand Down Expand Up @@ -341,6 +348,38 @@ private static string ReplaceDatabaseName(string connectionString, string newDbN
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
}

/// <summary>
/// Polls the health endpoint until the app returns a successful response, ensuring the
/// OrchardCore tenant pipeline has finished its lazy first-request initialization
/// before the Playwright tests begin.
/// </summary>
private static async Task WarmUpAsync(string baseAddress, string healthPath = "/health/live", int timeoutSeconds = 30)
{
using var client = new HttpClient();
var deadline = DateTime.UtcNow.AddSeconds(timeoutSeconds);

while (DateTime.UtcNow < deadline)
{
try
{
var response = await client.GetAsync($"{baseAddress}{healthPath}");
if (response.IsSuccessStatusCode)
{
return;
}
}
catch
{
// Server not yet accepting connections — keep waiting.
}

await Task.Delay(500);
}

throw new TimeoutException(
$"The application at '{baseAddress}' did not respond successfully at '{healthPath}' within {timeoutSeconds} seconds.");
}

private static string GetListeningAddress(WebApplication app)
{
var server = app.Services.GetRequiredService<IServer>();
Expand Down
8 changes: 6 additions & 2 deletions test/OrchardCore.Tests.Functional/Tests/Cms/AgencyTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ public AgencyTests(AgencyFixture fixture) : base(fixture) { }
public async Task DisplaysTheHomePageOfTheAgencyTheme()
{
var page = await Fixture.CreatePageAsync();
await page.GotoAsync("/");
var response = await page.GotoAsync("/");
Assert.NotNull(response);
Assert.True(response.Ok, $"Expected HTTP 200 but got {response.Status} for {response.Url}");
await Assertions.Expect(page.Locator("#services")).ToContainTextAsync("Lorem ipsum dolor sit amet consectetur");
await page.CloseAsync();
}
Expand All @@ -21,7 +23,9 @@ public async Task AgencyAdminLoginShouldWork()
{
var page = await Fixture.CreatePageAsync();
await page.LoginAsync();
await page.GotoAsync("/Admin");
var response = await page.GotoAsync("/Admin");
Assert.NotNull(response);
Assert.True(response.Ok, $"Expected HTTP 200 but got {response.Status} for {response.Url}");
await Assertions.Expect(page.Locator(".menu-admin")).ToHaveAttributeAsync("id", "adminMenu");
await page.CloseAsync();
}
Expand Down
8 changes: 6 additions & 2 deletions test/OrchardCore.Tests.Functional/Tests/Cms/BlogTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ public BlogTests(BlogFixture fixture) : base(fixture) { }
public async Task DisplaysTheHomePageOfTheBlogRecipe()
{
var page = await Fixture.CreatePageAsync();
await page.GotoAsync("/");
var response = await page.GotoAsync("/");
Assert.NotNull(response);
Assert.True(response.Ok, $"Expected HTTP 200 but got {response.Status} for {response.Url}");
await Assertions.Expect(page.Locator(".subheading")).ToContainTextAsync("This is the description of your blog");
await page.CloseAsync();
}
Expand All @@ -21,7 +23,9 @@ public async Task BlogAdminLoginShouldWork()
{
var page = await Fixture.CreatePageAsync();
await page.LoginAsync();
await page.GotoAsync("/Admin");
var response = await page.GotoAsync("/Admin");
Assert.NotNull(response);
Assert.True(response.Ok, $"Expected HTTP 200 but got {response.Status} for {response.Url}");
await Assertions.Expect(page.Locator(".menu-admin")).ToHaveAttributeAsync("id", "adminMenu");
await page.CloseAsync();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ public ComingSoonTests(ComingSoonFixture fixture) : base(fixture) { }
public async Task DisplaysTheHomePageOfTheComingSoonTheme()
{
var page = await Fixture.CreatePageAsync();
await page.GotoAsync("/");
var response = await page.GotoAsync("/");
Assert.NotNull(response);
Assert.True(response.Ok, $"Expected HTTP 200 but got {response.Status} for {response.Url}");
await Assertions.Expect(page.Locator("h1")).ToContainTextAsync("Coming Soon");
await Assertions.Expect(page.Locator("p")).ToContainTextAsync("We're working hard to finish the development of this site.");
await page.CloseAsync();
Expand All @@ -22,7 +24,9 @@ public async Task ComingSoonAdminLoginShouldWork()
{
var page = await Fixture.CreatePageAsync();
await page.LoginAsync();
await page.GotoAsync("/Admin");
var response = await page.GotoAsync("/Admin");
Assert.NotNull(response);
Assert.True(response.Ok, $"Expected HTTP 200 but got {response.Status} for {response.Url}");
await Assertions.Expect(page.Locator(".menu-admin")).ToHaveAttributeAsync("id", "adminMenu");
await page.CloseAsync();
}
Expand Down
8 changes: 6 additions & 2 deletions test/OrchardCore.Tests.Functional/Tests/Cms/HeadlessTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ public HeadlessTests(HeadlessFixture fixture) : base(fixture) { }
public async Task DisplaysTheLoginScreenForTheHeadlessTheme()
{
var page = await Fixture.CreatePageAsync();
await page.GotoAsync("/");
var response = await page.GotoAsync("/");
Assert.NotNull(response);
Assert.True(response.Ok, $"Expected HTTP 200 but got {response.Status} for {response.Url}");
await Assertions.Expect(page.Locator("h1")).ToContainTextAsync("Log in");
await page.CloseAsync();
}
Expand All @@ -21,7 +23,9 @@ public async Task HeadlessAdminLoginShouldWork()
{
var page = await Fixture.CreatePageAsync();
await page.LoginAsync();
await page.GotoAsync("/Admin");
var response = await page.GotoAsync("/Admin");
Assert.NotNull(response);
Assert.True(response.Ok, $"Expected HTTP 200 but got {response.Status} for {response.Url}");
await Assertions.Expect(page.Locator(".menu-admin")).ToHaveAttributeAsync("id", "adminMenu");
await page.CloseAsync();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ public MigrationsTests(MigrationsFixture fixture) : base(fixture) { }
public async Task DisplaysTheHomePageOfTheMigrationsRecipe()
{
var page = await Fixture.CreatePageAsync();
await page.GotoAsync("/");
var response = await page.GotoAsync("/");
Assert.NotNull(response);
Assert.True(response.Ok, $"Expected HTTP 200 but got {response.Status} for {response.Url}");
await Assertions.Expect(page.GetByText("Testing features having database migrations")).ToBeVisibleAsync();
await page.CloseAsync();
}
Expand All @@ -21,7 +23,9 @@ public async Task MigrationsAdminLoginShouldWork()
{
var page = await Fixture.CreatePageAsync();
await page.LoginAsync();
await page.GotoAsync("/Admin");
var response = await page.GotoAsync("/Admin");
Assert.NotNull(response);
Assert.True(response.Ok, $"Expected HTTP 200 but got {response.Status} for {response.Url}");
await Assertions.Expect(page.Locator(".menu-admin")).ToHaveAttributeAsync("id", "adminMenu");
await page.CloseAsync();
}
Expand Down
8 changes: 6 additions & 2 deletions test/OrchardCore.Tests.Functional/Tests/Cms/SaasTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ public ValueTask DisposeAsync()
public async Task DisplaysTheHomePageOfTheSaasTheme()
{
var page = await _fixture.CreatePageAsync();
await page.GotoAsync($"/{_fixture.Tenant.Prefix}");
var response = await page.GotoAsync($"/{_fixture.Tenant.Prefix}");
Assert.NotNull(response);
Assert.True(response.Ok, $"Expected HTTP 200 but got {response.Status} for {response.Url}");
await Assertions.Expect(page.Locator("h4")).ToContainTextAsync("Welcome to Orchard Core, your site has been successfully set up.");
await page.CloseAsync();
}
Expand All @@ -34,7 +36,9 @@ public async Task SaasAdminLoginShouldWork()
{
var page = await _fixture.CreatePageAsync();
await page.LoginAsync($"/{_fixture.Tenant.Prefix}");
await page.GotoAsync($"/{_fixture.Tenant.Prefix}/Admin");
var response = await page.GotoAsync($"/{_fixture.Tenant.Prefix}/Admin");
Assert.NotNull(response);
Assert.True(response.Ok, $"Expected HTTP 200 but got {response.Status} for {response.Url}");
await Assertions.Expect(page.Locator(".menu-admin")).ToHaveAttributeAsync("id", "adminMenu");
await page.CloseAsync();
}
Expand Down
4 changes: 3 additions & 1 deletion test/OrchardCore.Tests.Functional/Tests/Mvc/MvcTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ public ValueTask DisposeAsync()
public async Task ShouldDisplayHelloWorld()
{
var page = await _fixture.CreatePageAsync();
await page.GotoAsync("/");
var response = await page.GotoAsync("/");
Assert.NotNull(response);
Assert.True(response.Ok, $"Expected HTTP 200 but got {response.Status} for {response.Url}");
await Assertions.Expect(page.Locator("body")).ToContainTextAsync("Hello World");
await page.CloseAsync();
}
Expand Down
Loading