DesktopCardTests.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  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 DesktopCardTests(
  7. PlaywrightFixture fixture,
  8. ITestOutputHelper output) : E2ETestBase(fixture, output)
  9. {
  10. private readonly ITestOutputHelper _output = output;
  11. [Fact]
  12. public async Task User_Can_Add_And_Delete_Desktop()
  13. {
  14. var (context, page) = await CreatePageAsync();
  15. var desktopName = $"e2e-dt-{Guid.NewGuid():N}"[..16];
  16. try
  17. {
  18. await page.GotoAsync(fixture.BaseUrl);
  19. var layout = new MainLayoutPom(page);
  20. await layout.AssertLoadedAsync();
  21. await layout.GotoHardwareAsync();
  22. var hardwarePage = new HardwareTreePom(page);
  23. await hardwarePage.AssertLoadedAsync();
  24. await hardwarePage.GotoDesktopsListAsync();
  25. var listPage = new DesktopsListPom(page);
  26. await listPage.AssertLoadedAsync();
  27. await listPage.AddDesktopAsync(desktopName);
  28. // creation should navigate to details page
  29. await page.WaitForURLAsync($"**/resources/hardware/{desktopName}");
  30. // delete from details page (card)
  31. var card = new DesktopCardPom(page);
  32. await Assertions.Expect(card.DesktopItem(desktopName)).ToBeVisibleAsync();
  33. await card.DeleteDesktopAsync(desktopName);
  34. // after deletion you redirect (your page does Nav.NavigateTo("/hardware/tree"))
  35. await page.WaitForURLAsync("**/hardware/tree");
  36. }
  37. catch (Exception)
  38. {
  39. _output.WriteLine("TEST FAILED — Capturing diagnostics");
  40. _output.WriteLine($"Current URL: {page.Url}");
  41. _output.WriteLine("==== DOM SNAPSHOT START ====");
  42. _output.WriteLine(await page.ContentAsync());
  43. _output.WriteLine("==== DOM SNAPSHOT END ====");
  44. throw;
  45. }
  46. finally
  47. {
  48. await context.CloseAsync();
  49. }
  50. }
  51. [Fact]
  52. public async Task User_Can_Rename_Desktop_From_Details_Page()
  53. {
  54. var (context, page) = await CreatePageAsync();
  55. var originalName = $"e2e-dt-{Guid.NewGuid():N}"[..16];
  56. var renamedName = $"e2e-dt-{Guid.NewGuid():N}"[..16];
  57. try
  58. {
  59. await page.GotoAsync(fixture.BaseUrl);
  60. var layout = new MainLayoutPom(page);
  61. await layout.AssertLoadedAsync();
  62. await layout.GotoHardwareAsync();
  63. var hardwarePage = new HardwareTreePom(page);
  64. await hardwarePage.AssertLoadedAsync();
  65. await hardwarePage.GotoDesktopsListAsync();
  66. var listPage = new DesktopsListPom(page);
  67. await listPage.AssertLoadedAsync();
  68. await listPage.AddDesktopAsync(originalName);
  69. await page.WaitForURLAsync($"**/resources/hardware/{originalName}");
  70. var card = new DesktopCardPom(page);
  71. await Assertions.Expect(card.DesktopItem(originalName)).ToBeVisibleAsync();
  72. await card.RenameDesktopAsync(originalName, renamedName);
  73. await Assertions.Expect(card.DesktopItem(renamedName)).ToBeVisibleAsync();
  74. // cleanup
  75. await card.DeleteDesktopAsync(renamedName);
  76. await page.WaitForURLAsync("**/hardware/tree");
  77. }
  78. catch (Exception)
  79. {
  80. _output.WriteLine("TEST FAILED — Capturing diagnostics");
  81. _output.WriteLine($"Current URL: {page.Url}");
  82. _output.WriteLine("==== DOM SNAPSHOT START ====");
  83. _output.WriteLine(await page.ContentAsync());
  84. _output.WriteLine("==== DOM SNAPSHOT END ====");
  85. throw;
  86. }
  87. finally
  88. {
  89. await context.CloseAsync();
  90. }
  91. }
  92. [Fact]
  93. public async Task User_Can_Clone_Desktop_From_Details_Page()
  94. {
  95. var (context, page) = await CreatePageAsync();
  96. var originalName = $"e2e-dt-{Guid.NewGuid():N}"[..16];
  97. var cloneName = $"e2e-dt-{Guid.NewGuid():N}"[..16];
  98. try
  99. {
  100. await page.GotoAsync(fixture.BaseUrl);
  101. var layout = new MainLayoutPom(page);
  102. await layout.AssertLoadedAsync();
  103. await layout.GotoHardwareAsync();
  104. var hardwarePage = new HardwareTreePom(page);
  105. await hardwarePage.AssertLoadedAsync();
  106. await hardwarePage.GotoDesktopsListAsync();
  107. var listPage = new DesktopsListPom(page);
  108. await listPage.AssertLoadedAsync();
  109. await listPage.AddDesktopAsync(originalName);
  110. await page.WaitForURLAsync($"**/resources/hardware/{originalName}");
  111. var card = new DesktopCardPom(page);
  112. await Assertions.Expect(card.DesktopItem(originalName)).ToBeVisibleAsync();
  113. await card.CloneDesktopAsync(originalName, cloneName);
  114. await Assertions.Expect(card.DesktopItem(cloneName)).ToBeVisibleAsync();
  115. // cleanup: delete clone then original
  116. await card.DeleteDesktopAsync(cloneName);
  117. await page.WaitForURLAsync("**/hardware/tree");
  118. // go back to original and delete it too
  119. await page.GotoAsync($"{fixture.BaseUrl}/resources/hardware/{originalName}");
  120. await Assertions.Expect(card.DesktopItem(originalName)).ToBeVisibleAsync();
  121. await card.DeleteDesktopAsync(originalName);
  122. await page.WaitForURLAsync("**/hardware/tree");
  123. }
  124. catch (Exception)
  125. {
  126. _output.WriteLine("TEST FAILED — Capturing diagnostics");
  127. _output.WriteLine($"Current URL: {page.Url}");
  128. _output.WriteLine("==== DOM SNAPSHOT START ====");
  129. _output.WriteLine(await page.ContentAsync());
  130. _output.WriteLine("==== DOM SNAPSHOT END ====");
  131. throw;
  132. }
  133. finally
  134. {
  135. await context.CloseAsync();
  136. }
  137. }
  138. [Fact]
  139. public async Task User_Can_Edit_Desktop_Notes_And_Save()
  140. {
  141. var (context, page) = await CreatePageAsync();
  142. var desktopName = $"e2e-dt-{Guid.NewGuid():N}"[..16];
  143. var notes = $"notes-{Guid.NewGuid():N}";
  144. try
  145. {
  146. await page.GotoAsync(fixture.BaseUrl);
  147. var layout = new MainLayoutPom(page);
  148. await layout.AssertLoadedAsync();
  149. await layout.GotoHardwareAsync();
  150. var hardwarePage = new HardwareTreePom(page);
  151. await hardwarePage.AssertLoadedAsync();
  152. await hardwarePage.GotoDesktopsListAsync();
  153. var listPage = new DesktopsListPom(page);
  154. await listPage.AssertLoadedAsync();
  155. await listPage.AddDesktopAsync(desktopName);
  156. await page.WaitForURLAsync($"**/resources/hardware/{desktopName}");
  157. var card = new DesktopCardPom(page);
  158. await Assertions.Expect(card.DesktopItem(desktopName)).ToBeVisibleAsync();
  159. // start editing notes via MarkdownViewer edit button
  160. await card.NotesViewerEditButton(desktopName).ClickAsync();
  161. // ensure editor visible then fill + save
  162. await Assertions.Expect(card.NotesEditorRoot(desktopName)).ToBeVisibleAsync();
  163. await card.NotesEditorTextarea(desktopName).FillAsync(notes);
  164. await card.NotesEditorSave(desktopName).ClickAsync();
  165. // viewer back, and content should contain the notes
  166. await Assertions.Expect(card.NotesViewerRoot(desktopName)).ToBeVisibleAsync();
  167. await Assertions.Expect(card.NotesViewerRoot(desktopName)).ToContainTextAsync(notes);
  168. // cleanup
  169. await card.DeleteDesktopAsync(desktopName);
  170. await page.WaitForURLAsync("**/hardware/tree");
  171. }
  172. catch (Exception)
  173. {
  174. _output.WriteLine("TEST FAILED — Capturing diagnostics");
  175. _output.WriteLine($"Current URL: {page.Url}");
  176. _output.WriteLine("==== DOM SNAPSHOT START ====");
  177. _output.WriteLine(await page.ContentAsync());
  178. _output.WriteLine("==== DOM SNAPSHOT END ====");
  179. throw;
  180. }
  181. finally
  182. {
  183. await context.CloseAsync();
  184. }
  185. }
  186. [Fact]
  187. public async Task User_Can_Edit_Desktop_Notes_And_Cancel()
  188. {
  189. var (context, page) = await CreatePageAsync();
  190. var desktopName = $"e2e-dt-{Guid.NewGuid():N}"[..16];
  191. var notes = $"notes-{Guid.NewGuid():N}";
  192. try
  193. {
  194. await page.GotoAsync(fixture.BaseUrl);
  195. var layout = new MainLayoutPom(page);
  196. await layout.AssertLoadedAsync();
  197. await layout.GotoHardwareAsync();
  198. var hardwarePage = new HardwareTreePom(page);
  199. await hardwarePage.AssertLoadedAsync();
  200. await hardwarePage.GotoDesktopsListAsync();
  201. var listPage = new DesktopsListPom(page);
  202. await listPage.AssertLoadedAsync();
  203. await listPage.AddDesktopAsync(desktopName);
  204. await page.WaitForURLAsync($"**/resources/hardware/{desktopName}");
  205. var card = new DesktopCardPom(page);
  206. await Assertions.Expect(card.DesktopItem(desktopName)).ToBeVisibleAsync();
  207. await card.NotesViewerEditButton(desktopName).ClickAsync();
  208. await Assertions.Expect(card.NotesEditorRoot(desktopName)).ToBeVisibleAsync();
  209. await card.NotesEditorTextarea(desktopName).FillAsync(notes);
  210. await card.NotesEditorCancel(desktopName).ClickAsync();
  211. // viewer should be back, and should NOT show the cancelled notes
  212. await Assertions.Expect(card.NotesViewerRoot(desktopName)).ToBeVisibleAsync();
  213. await Assertions.Expect(card.NotesViewerRoot(desktopName)).Not.ToContainTextAsync(notes);
  214. // cleanup
  215. await card.DeleteDesktopAsync(desktopName);
  216. await page.WaitForURLAsync("**/hardware/tree");
  217. }
  218. catch (Exception)
  219. {
  220. _output.WriteLine("TEST FAILED — Capturing diagnostics");
  221. _output.WriteLine($"Current URL: {page.Url}");
  222. _output.WriteLine("==== DOM SNAPSHOT START ====");
  223. _output.WriteLine(await page.ContentAsync());
  224. _output.WriteLine("==== DOM SNAPSHOT END ====");
  225. throw;
  226. }
  227. finally
  228. {
  229. await context.CloseAsync();
  230. }
  231. }
  232. [Fact]
  233. public async Task User_Can_Add_And_Remove_Tags_From_Desktop_Card()
  234. {
  235. var (context, page) = await CreatePageAsync();
  236. var name = $"e2e-ap-{Guid.NewGuid():N}"[..16];
  237. try
  238. {
  239. await page.GotoAsync(fixture.BaseUrl);
  240. var layout = new MainLayoutPom(page);
  241. await layout.AssertLoadedAsync();
  242. await layout.GotoHardwareAsync();
  243. var hardwareTree = new HardwareTreePom(page);
  244. await hardwareTree.AssertLoadedAsync();
  245. await hardwareTree.GotoDesktopsListAsync();
  246. var list = new DesktopsListPom(page);
  247. await list.AssertLoadedAsync();
  248. await list.AddDesktopAsync(name);
  249. await page.WaitForURLAsync($"**/resources/hardware/{name}");
  250. var card = new DesktopCardPom(page);
  251. await Assertions.Expect(card.DesktopItem(name)).ToBeVisibleAsync();
  252. var tags = card.Tags;
  253. // -------------------------------------------------
  254. // Add multiple tags in one modal interaction
  255. // -------------------------------------------------
  256. await tags.AddTagsAsync("desktop", "Foo", "Bar", "Baz");
  257. await tags.AssertTagVisibleAsync("desktop", "Foo");
  258. await tags.AssertTagVisibleAsync("desktop", "Bar");
  259. await tags.AssertTagVisibleAsync("desktop", "Baz");
  260. // -------------------------------------------------
  261. // Remove a single tag
  262. // -------------------------------------------------
  263. await tags.RemoveTagAsync("desktop", "Bar");
  264. await tags.AssertTagNotVisibleAsync("desktop", "Bar");
  265. await tags.AssertTagVisibleAsync("desktop", "Foo");
  266. await tags.AssertTagVisibleAsync("desktop", "Baz");
  267. // -------------------------------------------------
  268. // Reload to verify persistence
  269. // -------------------------------------------------
  270. await page.ReloadAsync();
  271. await tags.AssertTagVisibleAsync("desktop", "Foo");
  272. await tags.AssertTagVisibleAsync("desktop", "Baz");
  273. await tags.AssertTagNotVisibleAsync("desktop", "Bar");
  274. await context.CloseAsync();
  275. }
  276. finally
  277. {
  278. await context.CloseAsync();
  279. }
  280. }
  281. }