-
Notifications
You must be signed in to change notification settings - Fork 308
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add playwright test for changing theme #4154
Add playwright test for changing theme #4154
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree on the confusion of why it didn't work the way you originally tried it. It'd also be nice to get some feedback from the Hosting folks about pulling in the dashboard ref here. Just test code, so probably fine, but an ack would be nice.
@@ -161,4 +162,4 @@ | |||
<PackageVersion Include="Newtonsoft.Json.Schema" Version="3.0.15" /> | |||
<!-- Introduced by Microsoft.Azure.Cosmos, https://github.com/Azure/azure-cosmos-dotnet-v3/issues/4302 --> | |||
</ItemGroup> | |||
</Project> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inadvertent change?
public Task<ResourceViewModelSubscription> SubscribeResourcesAsync(CancellationToken cancellationToken) => throw new NotImplementedException(); | ||
} | ||
|
||
public async Task<(string DashboardUrl, IPage Page)> SetupDashboardForPlaywrightAsync() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a huge fan of tuples in a public surface. But it's test code so probably OK.
catch (Exception) | ||
{ | ||
await Task.Delay(1000, cts.Token); | ||
await WaitUntilDashboardReadyAsync(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should there be a point at which this bails out?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also probably a loop rather than recursion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, looks like that's the 1 minute timeout on the cts. still, feels like a loop
FYI, I'm adding some playwright based tests in #3270 . But in that I'm using This waits for the dashboard to become available, and uses resiliency to handle retries - https://github.com/radical/aspire/blob/5a900f1f44018a84e6741c45c4d632a1b6e35090/tests/Shared/WorkloadTesting/AspireProject.cs#L408-L427 . And this connects with playwright, and verifies that the expected resources show up on the dashboard. |
{ | ||
await page.GotoAsync(url); | ||
} | ||
catch (Exception) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we want to retry on any exception type other than PlaywrightException ?
} | ||
catch (Exception) | ||
{ | ||
await Task.Delay(1000, cts.Token); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is 1000 reasonable? say, pages typically take 1100 ms to be ready, then it's adding 900ms delay on every test, and perhaps we end with 100 tests.
sometimes in these cases you see a backoff strategy. So starting with brief delays (or just calling GotoAsync again immediately) so the happy path on a machine where it's available fast has no delay. Then backing off progressively the delay for slower machines to release resources for the pages to actually start.
|
||
public async Task DisposeAsync() | ||
{ | ||
await Browser.DisposeAsync(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Browser.CloseAsync() seems canonical in their examples
public async Task DisposeAsync() | ||
{ | ||
await Browser.DisposeAsync(); | ||
PlaywrightInstance.Dispose(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it need disposing? I can't find in the docs.
I think in general you don't dispose Task<T>
without a reason
https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.dispose?view=net-8.0#system-threading-tasks-task-dispose
|
||
namespace Aspire.Hosting.Tests.Dashboard; | ||
|
||
public class AppbarTests : IClassFixture<PlaywrightFixture> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this the Fluent AppBar? In which case it should be capitalized AppBar
await settingsButton.ClickAsync(); | ||
var darkThemeCheckbox = page.GetByRole(AriaRole.Radio).And(page.GetByText("Dark")).First; | ||
await darkThemeCheckbox.ClickAsync(); | ||
Assert.Equal("dark", await page.Locator("html").First.GetAttributeAsync("data-theme")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assert it's not dark before you click the box?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and click again and assert it's light again?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also will this fail if the OS is set to dark theme up front (prefers-color-scheme: dark) ? if so it should instead test for what it is, click the box, check it changed, click the box, check it changed again.
var (_, page) = await _playwrightFixture.SetupDashboardForPlaywrightAsync(); | ||
var settingsButton = page.GetByRole(AriaRole.Button, new() | ||
{ | ||
Name = "Launch settings" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is matching the English string, right? Is there a way to find this button on any locale, as we want to test all localized builds. Perhaps via a class
or id
?
Name = "Launch settings" | ||
}); | ||
await settingsButton.ClickAsync(); | ||
var darkThemeCheckbox = page.GetByRole(AriaRole.Radio).And(page.GetByText("Dark")).First; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same issue with assuming English.
public async Task<(string DashboardUrl, IPage Page)> SetupDashboardForPlaywrightAsync() | ||
{ | ||
|
||
var url = "http://localhost:1234"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does it need a port at all?
using var testProgram = TestProgram.Create<PlaywrightFixture>( | ||
args, | ||
includeIntegrationServices: false, | ||
disableDashboard: false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this includeNodeApp actually?
aspire/tests/testproject/TestProject.AppHost/TestProgram.cs
Lines 151 to 157 in 612429c
public static TestProgram Create<T>( | |
string[]? args = null, | |
bool includeIntegrationServices = false, | |
bool includeNodeApp = false, | |
bool disableDashboard = true, | |
bool allowUnsecuredTransport = true, | |
bool randomizePorts = true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm but if that's so how is the named param compiling? I must be missing an overload
{ | ||
try | ||
{ | ||
await page.GotoAsync(url); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was looking to see whether there's a way to pass in the cts. But one can only pass a timeout (via PageGotoOptions) which is otherwise 30 seconds .. so I guess no reason to change that.
Was this closed by accident? |
@kvenkatrajan we are going to use Ankit’s e2e infrastructure so 90% of this pr content will be replaced :) |
thanks for working together on this, sounds like we'll end up with a single infrastructure and it will be easier for everyone. (when you have your new PR could you check whether any of the feedback above still applies?) |
Aspire.Hosting.Tests/Dashboard may not be the best place to put this test long-term. I made it local only for now.
I was unable to access the dashboard frontend from a browser when trying the approach in Aspire.Dashboard.Tests of just creating the dashboard frontend app - it would not connect. If anyone has an idea why that might be, I'm all ears.
I also ran into gRPC issues after orchestrating. Also seeking feedback on that, but in the meantime I injected a mock dashboard service so that there is no grpc connection.
Microsoft Reviewers: Open in CodeFlow