DesktopCardTests.cs 13 KB

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