GlobalSearchTests.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. using Microsoft.Playwright;
  2. using Tests.E2e.Infra;
  3. using Tests.E2e.PageObjectModels;
  4. using Xunit.Abstractions;
  5. namespace Tests.E2e;
  6. public class GlobalSearchTests(
  7. PlaywrightFixture fixture,
  8. ITestOutputHelper output) : E2ETestBase(fixture, output) {
  9. private readonly PlaywrightFixture _fixture = fixture;
  10. private readonly ITestOutputHelper _output = output;
  11. [Fact]
  12. public async Task User_Can_Search_For_Resources_Of_Every_Kind_And_Navigate_To_One() {
  13. (IBrowserContext context, IPage page) = await CreatePageAsync();
  14. // Shared random token in every seeded name so a single fragment hits
  15. // every kind, while a kind-prefixed query isolates one.
  16. var token = Guid.NewGuid().ToString("N")[..6];
  17. var seed = new (string Kind, string Name)[] {
  18. ("server", $"srv-{token}"),
  19. ("switch", $"sw-{token}"),
  20. ("firewall", $"fw-{token}"),
  21. ("router", $"rt-{token}"),
  22. ("accesspoint", $"ap-{token}"),
  23. ("ups", $"ups-{token}"),
  24. ("desktop", $"dt-{token}"),
  25. ("laptop", $"lt-{token}"),
  26. ("system", $"sys-{token}"),
  27. ("service", $"svc-{token}"),
  28. };
  29. try {
  30. await page.GotoAsync(_fixture.BaseUrl);
  31. await new MainLayoutPom(page).AssertLoadedAsync();
  32. // ───── Seed: one resource of every kind ─────
  33. await page.GotoAsync($"{_fixture.BaseUrl}/servers/list");
  34. await new ServersListPom(page).AddServerAsync($"srv-{token}");
  35. await page.GotoAsync($"{_fixture.BaseUrl}/switches/list");
  36. await new SwitchListPom(page).AddSwitchAsync($"sw-{token}");
  37. await page.GotoAsync($"{_fixture.BaseUrl}/firewalls/list");
  38. await new FirewallsListPom(page).AddFirewallAsync($"fw-{token}");
  39. await page.GotoAsync($"{_fixture.BaseUrl}/routers/list");
  40. await new RouterListPom(page).AddRouterAsync($"rt-{token}");
  41. await page.GotoAsync($"{_fixture.BaseUrl}/accesspoints/list");
  42. await new AccessPointsListPom(page).AddAccessPointAsync($"ap-{token}");
  43. await page.GotoAsync($"{_fixture.BaseUrl}/ups/list");
  44. await new UpsListPom(page).AddUpsAsync($"ups-{token}");
  45. await page.GotoAsync($"{_fixture.BaseUrl}/desktops/list");
  46. await new DesktopsListPom(page).AddDesktopAsync($"dt-{token}");
  47. await page.GotoAsync($"{_fixture.BaseUrl}/laptops/list");
  48. await new LaptopListPom(page).AddLaptopAsync($"lt-{token}");
  49. await page.GotoAsync($"{_fixture.BaseUrl}/systems/list");
  50. await new SystemsListPom(page).AddSystemAsync($"sys-{token}");
  51. await page.GotoAsync($"{_fixture.BaseUrl}/services/list");
  52. await new ServicesListPom(page).AddServiceAsync($"svc-{token}");
  53. var search = new GlobalSearchPom(page);
  54. // ───── Per-kind search: each unique name surfaces its own kind ─────
  55. foreach ((string Kind, string Name) entry in seed) {
  56. await search.SearchAsync(entry.Name);
  57. await search.AssertResultExistsAsync(entry.Kind, entry.Name);
  58. }
  59. // ───── Cross-kind search: shared token surfaces results from
  60. // multiple kinds in the same dropdown. Top N is capped at 8;
  61. // within an equal-score tier ties break alphabetically by name,
  62. // so the kinds asserted here are those guaranteed to land
  63. // inside the cap given the seeded name prefixes.
  64. await search.SearchAsync(token);
  65. await search.AssertResultExistsAsync("service", $"svc-{token}");
  66. await search.AssertResultExistsAsync("server", $"srv-{token}");
  67. await search.AssertResultExistsAsync("switch", $"sw-{token}");
  68. // ───── Click navigates to the resource page ─────
  69. await search.SearchAsync($"svc-{token}");
  70. await search.ClickResultAsync("service", $"svc-{token}");
  71. await page.WaitForURLAsync($"**/resources/services/svc-{token}");
  72. }
  73. catch (Exception) {
  74. _output.WriteLine("TEST FAILED — Capturing diagnostics");
  75. _output.WriteLine($"Current URL: {page.Url}");
  76. var html = await page.ContentAsync();
  77. _output.WriteLine("==== DOM SNAPSHOT START ====");
  78. _output.WriteLine(html);
  79. _output.WriteLine("==== DOM SNAPSHOT END ====");
  80. throw;
  81. }
  82. finally {
  83. await context.CloseAsync();
  84. }
  85. }
  86. }