ServiceCardTests.cs 7.8 KB

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