ServiceCardTests.cs 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  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 ServiceCardTests(
  7. PlaywrightFixture fixture,
  8. ITestOutputHelper output) : E2ETestBase(fixture, output) {
  9. private readonly PlaywrightFixture _fixture = fixture;
  10. private readonly ITestOutputHelper _output = output;
  11. // =============================================================
  12. // Rename / Clone / Delete Flow
  13. // =============================================================
  14. [Fact]
  15. public async Task User_Can_Rename_Clone_And_Delete_Service_From_Details_Page() {
  16. (IBrowserContext context, IPage page) = await CreatePageAsync();
  17. var originalName = $"e2e-svc-{Guid.NewGuid():N}"[..16];
  18. var renamedName = $"e2e-svc-rn-{Guid.NewGuid():N}"[..16];
  19. var cloneName = $"e2e-svc-cl-{Guid.NewGuid():N}"[..16];
  20. try {
  21. await page.GotoAsync($"{_fixture.BaseUrl}/services/list");
  22. var list = new ServicesListPom(page);
  23. await list.AssertLoadedAsync();
  24. await list.AddServiceAsync(originalName);
  25. if (!page.Url.Contains($"/resources/services/{originalName}",
  26. StringComparison.OrdinalIgnoreCase))
  27. await list.OpenServiceAsync(originalName);
  28. var card = new ServiceCardPom(page);
  29. await card.AssertVisibleAsync(originalName);
  30. // -------------------------
  31. // Rename
  32. // -------------------------
  33. await card.RenameAsync(originalName, renamedName);
  34. await card.AssertVisibleAsync(renamedName);
  35. // -------------------------
  36. // Clone
  37. // -------------------------
  38. await card.CloneAsync(renamedName, cloneName);
  39. await card.AssertVisibleAsync(cloneName);
  40. // -------------------------
  41. // Delete clone
  42. // -------------------------
  43. await card.DeleteAsync(cloneName);
  44. await page.WaitForURLAsync("**/services/list");
  45. // Delete renamed original
  46. await page.GotoAsync($"{_fixture.BaseUrl}/resources/services/{renamedName}");
  47. await card.AssertVisibleAsync(renamedName);
  48. await card.DeleteAsync(renamedName);
  49. await page.WaitForURLAsync("**/services/list");
  50. }
  51. catch (Exception) {
  52. _output.WriteLine("TEST FAILED — Capturing diagnostics");
  53. _output.WriteLine($"Current URL: {page.Url}");
  54. var html = await page.ContentAsync();
  55. _output.WriteLine("==== DOM SNAPSHOT START ====");
  56. _output.WriteLine(html);
  57. _output.WriteLine("==== DOM SNAPSHOT END ====");
  58. throw;
  59. }
  60. finally {
  61. await context.CloseAsync();
  62. }
  63. }
  64. // =============================================================
  65. // Edit Flow Test
  66. // =============================================================
  67. [Fact]
  68. public async Task User_Can_Edit_And_Save_Service() {
  69. (IBrowserContext context, IPage page) = await CreatePageAsync();
  70. var name = $"e2e-svc-edit-{Guid.NewGuid():N}"[..16];
  71. try {
  72. await page.GotoAsync($"{_fixture.BaseUrl}/services/list");
  73. var list = new ServicesListPom(page);
  74. await list.AddServiceAsync(name);
  75. if (!page.Url.Contains($"/resources/services/{name}",
  76. StringComparison.OrdinalIgnoreCase))
  77. await list.OpenServiceAsync(name);
  78. var card = new ServiceCardPom(page);
  79. await card.AssertVisibleAsync(name);
  80. await card.BeginEditAsync(name);
  81. // Fill via proper test ids
  82. await card.IpInput(name).FillAsync("127.0.0.1");
  83. await card.PortInput(name).FillAsync("8080");
  84. await card.ProtocolInput(name).FillAsync("http");
  85. await card.UrlInput(name).FillAsync("http://localhost:8080");
  86. await card.SaveAsync(name);
  87. // Verify edit mode exited
  88. await Assertions.Expect(card.EditButton(name)).ToBeVisibleAsync();
  89. // Verify persisted values
  90. await Assertions.Expect(card.IpValue(name)).ToHaveTextAsync("127.0.0.1");
  91. await Assertions.Expect(card.PortValue(name)).ToHaveTextAsync("8080");
  92. await Assertions.Expect(card.ProtocolValue(name)).ToHaveTextAsync("http");
  93. }
  94. finally {
  95. await context.CloseAsync();
  96. }
  97. }
  98. // =============================================================
  99. // Cancel Edit Test
  100. // =============================================================
  101. [Fact]
  102. public async Task User_Can_Cancel_Edit_Without_Saving() {
  103. (IBrowserContext context, IPage page) = await CreatePageAsync();
  104. var name = $"e2e-svc-cancel-{Guid.NewGuid():N}"[..16];
  105. try {
  106. await page.GotoAsync($"{_fixture.BaseUrl}/services/list");
  107. var list = new ServicesListPom(page);
  108. await list.AddServiceAsync(name);
  109. if (!page.Url.Contains($"/resources/services/{name}",
  110. StringComparison.OrdinalIgnoreCase))
  111. await list.OpenServiceAsync(name);
  112. var card = new ServiceCardPom(page);
  113. await card.AssertVisibleAsync(name);
  114. await card.BeginEditAsync(name);
  115. await card.IpInput(name).FillAsync("should-not-save");
  116. await card.CancelAsync(name);
  117. // Confirm edit mode exited
  118. await Assertions.Expect(card.EditButton(name)).ToBeVisibleAsync();
  119. // Confirm value did NOT persist
  120. await Assertions.Expect(card.IpValue(name)).Not.ToBeVisibleAsync();
  121. }
  122. finally {
  123. await context.CloseAsync();
  124. }
  125. }
  126. [Fact]
  127. public async Task User_Can_Add_And_Remove_Tags_From_Service_Card() {
  128. (IBrowserContext context, IPage page) = await CreatePageAsync();
  129. var name = $"e2e-ap-{Guid.NewGuid():N}"[..16];
  130. try {
  131. await page.GotoAsync($"{_fixture.BaseUrl}/services/list");
  132. var list = new ServicesListPom(page);
  133. await list.AssertLoadedAsync();
  134. await list.AddServiceAsync(name);
  135. await page.WaitForURLAsync($"**/resources/services/{name}");
  136. var card = new ServiceCardPom(page);
  137. await card.AssertVisibleAsync(name);
  138. TagsPom tags = card.Tags;
  139. // -------------------------------------------------
  140. // Add multiple tags in one modal interaction
  141. // -------------------------------------------------
  142. await tags.AddTagsAsync("service", "Foo", "Bar", "Baz");
  143. await tags.AssertTagVisibleAsync("service", "Foo");
  144. await tags.AssertTagVisibleAsync("service", "Bar");
  145. await tags.AssertTagVisibleAsync("service", "Baz");
  146. // -------------------------------------------------
  147. // Remove a single tag
  148. // -------------------------------------------------
  149. await tags.RemoveTagAsync("service", "Bar");
  150. await tags.AssertTagNotVisibleAsync("service", "Bar");
  151. await tags.AssertTagVisibleAsync("service", "Foo");
  152. await tags.AssertTagVisibleAsync("service", "Baz");
  153. // -------------------------------------------------
  154. // Reload to verify persistence
  155. // -------------------------------------------------
  156. await page.ReloadAsync();
  157. await tags.AssertTagVisibleAsync("service", "Foo");
  158. await tags.AssertTagVisibleAsync("service", "Baz");
  159. await tags.AssertTagNotVisibleAsync("service", "Bar");
  160. await context.CloseAsync();
  161. }
  162. finally {
  163. await context.CloseAsync();
  164. }
  165. }
  166. }