SystemCardTests.cs 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  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 SystemCardTests(
  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_System() {
  16. (IBrowserContext context, IPage page) = await CreatePageAsync();
  17. var originalName = $"e2e-sys-{Guid.NewGuid():N}"[..16];
  18. var renamedName = $"e2e-sys-rn-{Guid.NewGuid():N}"[..16];
  19. var cloneName = $"e2e-sys-cl-{Guid.NewGuid():N}"[..16];
  20. try {
  21. await page.GotoAsync($"{_fixture.BaseUrl}/systems/list");
  22. var list = new SystemsListPom(page);
  23. await list.AssertLoadedAsync();
  24. await list.AddSystemAsync(originalName);
  25. if (!page.Url.Contains($"/resources/systems/{originalName}",
  26. StringComparison.OrdinalIgnoreCase))
  27. await list.OpenSystemAsync(originalName);
  28. var card = new SystemCardPom(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("**/systems/list");
  45. // Delete renamed original
  46. await page.GotoAsync($"{_fixture.BaseUrl}/resources/systems/{renamedName}");
  47. await card.AssertVisibleAsync(renamedName);
  48. await card.DeleteAsync(renamedName);
  49. await page.WaitForURLAsync("**/systems/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
  66. // ============================================================
  67. [Fact]
  68. public async Task User_Can_Edit_And_Save_System() {
  69. (IBrowserContext context, IPage page) = await CreatePageAsync();
  70. var name = $"e2e-sys-edit-{Guid.NewGuid():N}"[..16];
  71. try {
  72. await page.GotoAsync($"{_fixture.BaseUrl}/systems/list");
  73. var list = new SystemsListPom(page);
  74. await list.AddSystemAsync(name);
  75. if (!page.Url.Contains($"/resources/systems/{name}",
  76. StringComparison.OrdinalIgnoreCase))
  77. await list.OpenSystemAsync(name);
  78. var card = new SystemCardPom(page);
  79. await card.AssertVisibleAsync(name);
  80. await card.BeginEditAsync(name);
  81. // Edit fields
  82. await card.TypeSelect(name).SelectOptionAsync(new SelectOptionValue { Index = 0 });
  83. await card.OsInput(name).FillAsync("Ubuntu 22.04");
  84. await card.CoresInput(name).FillAsync("8");
  85. await card.RamInput(name).FillAsync("16");
  86. await card.SaveAsync(name);
  87. // Verify read mode restored
  88. await Assertions.Expect(card.EditButton(name)).ToBeVisibleAsync();
  89. }
  90. finally {
  91. await context.CloseAsync();
  92. }
  93. }
  94. [Fact]
  95. public async Task Saving_Without_Touching_Type_Persists_The_Displayed_Default() {
  96. (IBrowserContext context, IPage page) = await CreatePageAsync();
  97. var name = $"e2e-sys-type-{Guid.NewGuid():N}"[..16];
  98. try {
  99. await page.GotoAsync($"{_fixture.BaseUrl}/systems/list");
  100. var list = new SystemsListPom(page);
  101. await list.AddSystemAsync(name);
  102. if (!page.Url.Contains($"/resources/systems/{name}",
  103. StringComparison.OrdinalIgnoreCase))
  104. await list.OpenSystemAsync(name);
  105. var card = new SystemCardPom(page);
  106. await card.AssertVisibleAsync(name);
  107. // The dropdown shows 'baremetal' for a fresh system; save without
  108. // touching it — the displayed default must actually persist (#306).
  109. await card.BeginEditAsync(name);
  110. await card.SaveAsync(name);
  111. await Assertions.Expect(card.TypeValue(name)).ToHaveTextAsync("baremetal");
  112. await page.ReloadAsync();
  113. await card.AssertVisibleAsync(name);
  114. await Assertions.Expect(card.TypeValue(name)).ToHaveTextAsync("baremetal");
  115. }
  116. finally {
  117. await context.CloseAsync();
  118. }
  119. }
  120. // ============================================================
  121. // Cancel Edit
  122. // ============================================================
  123. [Fact]
  124. public async Task User_Can_Cancel_System_Edit() {
  125. (IBrowserContext context, IPage page) = await CreatePageAsync();
  126. var name = $"e2e-sys-cancel-{Guid.NewGuid():N}"[..16];
  127. try {
  128. await page.GotoAsync($"{_fixture.BaseUrl}/systems/list");
  129. var list = new SystemsListPom(page);
  130. await list.AddSystemAsync(name);
  131. if (!page.Url.Contains($"/resources/systems/{name}",
  132. StringComparison.OrdinalIgnoreCase))
  133. await list.OpenSystemAsync(name);
  134. var card = new SystemCardPom(page);
  135. await card.AssertVisibleAsync(name);
  136. await card.BeginEditAsync(name);
  137. await card.OsInput(name).FillAsync("Should Not Save");
  138. await card.CancelAsync(name);
  139. await Assertions.Expect(card.EditButton(name)).ToBeVisibleAsync();
  140. }
  141. finally {
  142. await context.CloseAsync();
  143. }
  144. }
  145. // ============================================================
  146. // Drive Flow
  147. // ============================================================
  148. [Fact]
  149. public async Task User_Can_Add_And_Edit_System_Drive() {
  150. (IBrowserContext context, IPage page) = await CreatePageAsync();
  151. var name = $"e2e-sys-drive-{Guid.NewGuid():N}"[..16];
  152. try {
  153. await page.GotoAsync($"{_fixture.BaseUrl}/systems/list");
  154. var list = new SystemsListPom(page);
  155. await list.AddSystemAsync(name);
  156. if (!page.Url.Contains($"/resources/systems/{name}",
  157. StringComparison.OrdinalIgnoreCase))
  158. await list.OpenSystemAsync(name);
  159. var card = new SystemCardPom(page);
  160. await card.AssertVisibleAsync(name);
  161. await card.AddDriveAsync(name, "ssd", 512);
  162. }
  163. finally {
  164. await context.CloseAsync();
  165. }
  166. }
  167. [Fact]
  168. public async Task User_Can_Add_And_Remove_Tags_From_System_Card() {
  169. (IBrowserContext context, IPage page) = await CreatePageAsync();
  170. var name = $"e2e-ap-{Guid.NewGuid():N}"[..16];
  171. try {
  172. await page.GotoAsync($"{_fixture.BaseUrl}/systems/list");
  173. var list = new SystemsListPom(page);
  174. await list.AssertLoadedAsync();
  175. await list.AddSystemAsync(name);
  176. await page.WaitForURLAsync($"**/resources/systems/{name}");
  177. var card = new SystemCardPom(page);
  178. await card.AssertVisibleAsync(name);
  179. TagsPom tags = card.Tags;
  180. // -------------------------------------------------
  181. // Add multiple tags in one modal interaction
  182. // -------------------------------------------------
  183. await tags.AddTagsAsync("system", "Foo", "Bar", "Baz");
  184. await tags.AssertTagVisibleAsync("system", "Foo");
  185. await tags.AssertTagVisibleAsync("system", "Bar");
  186. await tags.AssertTagVisibleAsync("system", "Baz");
  187. // -------------------------------------------------
  188. // Remove a single tag
  189. // -------------------------------------------------
  190. await tags.RemoveTagAsync("system", "Bar");
  191. await tags.AssertTagNotVisibleAsync("system", "Bar");
  192. await tags.AssertTagVisibleAsync("system", "Foo");
  193. await tags.AssertTagVisibleAsync("system", "Baz");
  194. // -------------------------------------------------
  195. // Reload to verify persistence
  196. // -------------------------------------------------
  197. await page.ReloadAsync();
  198. await tags.AssertTagVisibleAsync("system", "Foo");
  199. await tags.AssertTagVisibleAsync("system", "Baz");
  200. await tags.AssertTagNotVisibleAsync("system", "Bar");
  201. await context.CloseAsync();
  202. }
  203. finally {
  204. await context.CloseAsync();
  205. }
  206. }
  207. }