|
|
@@ -0,0 +1,108 @@
|
|
|
+using Microsoft.Playwright;
|
|
|
+using Tests.E2e.Infra;
|
|
|
+using Tests.E2e.PageObjectModels;
|
|
|
+using Xunit.Abstractions;
|
|
|
+
|
|
|
+namespace Tests.E2e;
|
|
|
+
|
|
|
+public class GlobalSearchTests(
|
|
|
+ PlaywrightFixture fixture,
|
|
|
+ ITestOutputHelper output) : E2ETestBase(fixture, output) {
|
|
|
+ private readonly PlaywrightFixture _fixture = fixture;
|
|
|
+ private readonly ITestOutputHelper _output = output;
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public async Task User_Can_Search_For_Resources_Of_Every_Kind_And_Navigate_To_One() {
|
|
|
+ (IBrowserContext context, IPage page) = await CreatePageAsync();
|
|
|
+
|
|
|
+ // Shared random token in every seeded name so a single fragment hits
|
|
|
+ // every kind, while a kind-prefixed query isolates one.
|
|
|
+ var token = Guid.NewGuid().ToString("N")[..6];
|
|
|
+
|
|
|
+ var seed = new (string Kind, string Name)[] {
|
|
|
+ ("server", $"srv-{token}"),
|
|
|
+ ("switch", $"sw-{token}"),
|
|
|
+ ("firewall", $"fw-{token}"),
|
|
|
+ ("router", $"rt-{token}"),
|
|
|
+ ("accesspoint", $"ap-{token}"),
|
|
|
+ ("ups", $"ups-{token}"),
|
|
|
+ ("desktop", $"dt-{token}"),
|
|
|
+ ("laptop", $"lt-{token}"),
|
|
|
+ ("system", $"sys-{token}"),
|
|
|
+ ("service", $"svc-{token}"),
|
|
|
+ };
|
|
|
+
|
|
|
+ try {
|
|
|
+ await page.GotoAsync(_fixture.BaseUrl);
|
|
|
+ await new MainLayoutPom(page).AssertLoadedAsync();
|
|
|
+
|
|
|
+ // ───── Seed: one resource of every kind ─────
|
|
|
+ await page.GotoAsync($"{_fixture.BaseUrl}/servers/list");
|
|
|
+ await new ServersListPom(page).AddServerAsync($"srv-{token}");
|
|
|
+
|
|
|
+ await page.GotoAsync($"{_fixture.BaseUrl}/switches/list");
|
|
|
+ await new SwitchListPom(page).AddSwitchAsync($"sw-{token}");
|
|
|
+
|
|
|
+ await page.GotoAsync($"{_fixture.BaseUrl}/firewalls/list");
|
|
|
+ await new FirewallsListPom(page).AddFirewallAsync($"fw-{token}");
|
|
|
+
|
|
|
+ await page.GotoAsync($"{_fixture.BaseUrl}/routers/list");
|
|
|
+ await new RouterListPom(page).AddRouterAsync($"rt-{token}");
|
|
|
+
|
|
|
+ await page.GotoAsync($"{_fixture.BaseUrl}/accesspoints/list");
|
|
|
+ await new AccessPointsListPom(page).AddAccessPointAsync($"ap-{token}");
|
|
|
+
|
|
|
+ await page.GotoAsync($"{_fixture.BaseUrl}/ups/list");
|
|
|
+ await new UpsListPom(page).AddUpsAsync($"ups-{token}");
|
|
|
+
|
|
|
+ await page.GotoAsync($"{_fixture.BaseUrl}/desktops/list");
|
|
|
+ await new DesktopsListPom(page).AddDesktopAsync($"dt-{token}");
|
|
|
+
|
|
|
+ await page.GotoAsync($"{_fixture.BaseUrl}/laptops/list");
|
|
|
+ await new LaptopListPom(page).AddLaptopAsync($"lt-{token}");
|
|
|
+
|
|
|
+ await page.GotoAsync($"{_fixture.BaseUrl}/systems/list");
|
|
|
+ await new SystemsListPom(page).AddSystemAsync($"sys-{token}");
|
|
|
+
|
|
|
+ await page.GotoAsync($"{_fixture.BaseUrl}/services/list");
|
|
|
+ await new ServicesListPom(page).AddServiceAsync($"svc-{token}");
|
|
|
+
|
|
|
+ var search = new GlobalSearchPom(page);
|
|
|
+
|
|
|
+ // ───── Per-kind search: each unique name surfaces its own kind ─────
|
|
|
+ foreach ((string Kind, string Name) entry in seed) {
|
|
|
+ await search.SearchAsync(entry.Name);
|
|
|
+ await search.AssertResultExistsAsync(entry.Kind, entry.Name);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ───── Cross-kind search: shared token surfaces results from
|
|
|
+ // multiple kinds in the same dropdown. Top N is capped at 8;
|
|
|
+ // within an equal-score tier ties break alphabetically by name,
|
|
|
+ // so the kinds asserted here are those guaranteed to land
|
|
|
+ // inside the cap given the seeded name prefixes.
|
|
|
+ await search.SearchAsync(token);
|
|
|
+ await search.AssertResultExistsAsync("service", $"svc-{token}");
|
|
|
+ await search.AssertResultExistsAsync("server", $"srv-{token}");
|
|
|
+ await search.AssertResultExistsAsync("switch", $"sw-{token}");
|
|
|
+
|
|
|
+ // ───── Click navigates to the resource page ─────
|
|
|
+ await search.SearchAsync($"svc-{token}");
|
|
|
+ await search.ClickResultAsync("service", $"svc-{token}");
|
|
|
+ await page.WaitForURLAsync($"**/resources/services/svc-{token}");
|
|
|
+ }
|
|
|
+ catch (Exception) {
|
|
|
+ _output.WriteLine("TEST FAILED — Capturing diagnostics");
|
|
|
+ _output.WriteLine($"Current URL: {page.Url}");
|
|
|
+
|
|
|
+ var html = await page.ContentAsync();
|
|
|
+ _output.WriteLine("==== DOM SNAPSHOT START ====");
|
|
|
+ _output.WriteLine(html);
|
|
|
+ _output.WriteLine("==== DOM SNAPSHOT END ====");
|
|
|
+
|
|
|
+ throw;
|
|
|
+ }
|
|
|
+ finally {
|
|
|
+ await context.CloseAsync();
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|