AccessPointCardPom.cs 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. using System.Globalization;
  2. using Microsoft.Playwright;
  3. namespace Tests.E2e.PageObjectModels;
  4. public class AccessPointCardPom(IPage page) {
  5. public TagsPom Tags => new(page);
  6. public LabelsPom Labels => new(page);
  7. public PortsPom Ports => new(page);
  8. private const string _portsPrefix = "accesspoint-ports";
  9. // Modals
  10. public ILocator DeleteConfirmModal => page.GetByTestId("AccessPoint-confirm-modal");
  11. public ILocator DeleteConfirmButton => page.GetByTestId("AccessPoint-confirm-modal-confirm");
  12. public ILocator DeleteCancelButton => page.GetByTestId("AccessPoint-confirm-modal-cancel");
  13. public ILocator RenameModal => page.GetByTestId("accesspoint-rename-string-value-modal");
  14. public ILocator RenameModalInput => page.GetByTestId("accesspoint-rename-string-value-modal-input");
  15. public ILocator RenameModalSubmit => page.GetByTestId("accesspoint-rename-string-value-modal-submit");
  16. public ILocator RenameModalCancel => page.GetByTestId("accesspoint-rename-string-value-modal-cancel");
  17. public ILocator CloneModal => page.GetByTestId("accesspoint-clone-string-value-modal");
  18. public ILocator CloneModalInput => page.GetByTestId("accesspoint-clone-string-value-modal-input");
  19. public ILocator CloneModalSubmit => page.GetByTestId("accesspoint-clone-string-value-modal-submit");
  20. public ILocator CloneModalCancel => page.GetByTestId("accesspoint-clone-string-value-modal-cancel");
  21. // Root
  22. public ILocator Card(string accessPointName)
  23. => page.GetByTestId($"accesspoint-item-{Sanitize(accessPointName)}");
  24. // Link / navigation
  25. public ILocator OpenLink(string accessPointName)
  26. => Card(accessPointName).GetByTestId("open-accesspoint-link");
  27. // Top-right actions (view mode)
  28. public ILocator EditButton(string accessPointName)
  29. => Card(accessPointName).GetByTestId("edit-accesspoint-button");
  30. public ILocator RenameButton(string accessPointName)
  31. => Card(accessPointName).GetByTestId("rename-accesspoint-button");
  32. public ILocator CloneButton(string accessPointName)
  33. => Card(accessPointName).GetByTestId("clone-accesspoint-button");
  34. public ILocator DeleteButton(string accessPointName)
  35. => Card(accessPointName).GetByTestId("delete-accesspoint-button");
  36. // Top-right actions (edit mode)
  37. public ILocator SaveButton(string accessPointName)
  38. => Card(accessPointName).GetByTestId("save-accesspoint-button");
  39. public ILocator CancelButton(string accessPointName)
  40. => Card(accessPointName).GetByTestId("cancel-accesspoint-button");
  41. // Fields
  42. public ILocator ModelSection(string accessPointName)
  43. => Card(accessPointName).GetByTestId("accesspoint-model-section");
  44. public ILocator ModelInput(string accessPointName)
  45. => Card(accessPointName).GetByTestId("accesspoint-model-input");
  46. public ILocator ModelValue(string accessPointName)
  47. => Card(accessPointName).GetByTestId("accesspoint-model-value");
  48. public ILocator SpeedSection(string accessPointName)
  49. => Card(accessPointName).GetByTestId("accesspoint-speed-section");
  50. public ILocator SpeedInput(string accessPointName)
  51. => Card(accessPointName).GetByTestId("accesspoint-speed-input");
  52. public ILocator SpeedValue(string accessPointName)
  53. => Card(accessPointName).GetByTestId("accesspoint-speed-value");
  54. // Notes (prefixed components)
  55. public ILocator NotesViewerRoot(string accessPointName)
  56. => Card(accessPointName).GetByTestId("accesspoint-notes-viewer-markdown-viewer");
  57. public ILocator NotesViewerContent(string accessPointName)
  58. => Card(accessPointName).GetByTestId("accesspoint-notes-viewer-markdown-viewer-content");
  59. public ILocator NotesViewerEmpty(string accessPointName)
  60. => Card(accessPointName).GetByTestId("accesspoint-notes-viewer-markdown-viewer-empty");
  61. public ILocator NotesEditorRoot(string accessPointName)
  62. => Card(accessPointName).GetByTestId("accesspoint-notes-editor-markdown-editor");
  63. public ILocator NotesEditorTextarea(string accessPointName)
  64. => Card(accessPointName).GetByTestId("accesspoint-notes-editor-markdown-editor-textarea");
  65. // -------------------------------------------------
  66. // Navigation (hardware details page)
  67. // -------------------------------------------------
  68. public async Task GotoHardwareAsync(string baseUrl, string hardwareName) {
  69. await page.GotoAsync($"{baseUrl}/resources/hardware/{hardwareName}");
  70. await AssertCardVisibleAsync(hardwareName);
  71. }
  72. public async Task AssertCardVisibleAsync(string accessPointName) =>
  73. await Assertions.Expect(Card(accessPointName)).ToBeVisibleAsync();
  74. // -------------------------------------------------
  75. // Actions
  76. // -------------------------------------------------
  77. public async Task OpenAsync(string accessPointName) {
  78. await OpenLink(accessPointName).ClickAsync();
  79. await page.WaitForURLAsync($"**/resources/hardware/{accessPointName}");
  80. }
  81. public async Task BeginEditAsync(string accessPointName) {
  82. await EditButton(accessPointName).ClickAsync();
  83. await Assertions.Expect(ModelInput(accessPointName)).ToBeVisibleAsync();
  84. }
  85. public async Task SetModelAsync(string accessPointName, string model) =>
  86. await ModelInput(accessPointName).FillAsync(model);
  87. public async Task SetSpeedAsync(string accessPointName, double speed) =>
  88. await SpeedInput(accessPointName).FillAsync(speed.ToString(CultureInfo.InvariantCulture));
  89. public async Task SetNotesAsync(string accessPointName, string notes) =>
  90. await NotesEditorTextarea(accessPointName).FillAsync(notes);
  91. public async Task TypeNotesAsync(string accessPointName, string text) =>
  92. await NotesEditorTextarea(accessPointName).PressSequentiallyAsync(
  93. text,
  94. new LocatorPressSequentiallyOptions { Delay = 30 });
  95. public async Task TypeNotesLineAfterFirstLineAsync(string accessPointName, string line) {
  96. // Place the caret at the end of the first line via setSelectionRange:
  97. // Home/End/Control+Home don't move the caret on macOS Chromium, so
  98. // keyboard-based positioning silently types at the wrong place there.
  99. // The typing itself stays as real key events.
  100. ILocator textarea = NotesEditorTextarea(accessPointName);
  101. await textarea.FocusAsync();
  102. await textarea.EvaluateAsync(
  103. @"el => {
  104. const pos = el.value.indexOf('\n');
  105. const at = pos < 0 ? el.value.length : pos;
  106. el.setSelectionRange(at, at);
  107. }");
  108. await page.Keyboard.PressAsync("Enter");
  109. await TypeNotesAsync(accessPointName, line);
  110. }
  111. public async Task SaveAsync(string accessPointName) {
  112. await SaveButton(accessPointName).ClickAsync();
  113. await Assertions.Expect(ModelSection(accessPointName)).ToBeVisibleAsync();
  114. }
  115. public async Task CancelEditAsync(string accessPointName) {
  116. await CancelButton(accessPointName).ClickAsync();
  117. await Assertions.Expect(EditButton(accessPointName)).ToBeVisibleAsync();
  118. }
  119. public async Task DeleteAsync(string accessPointName) {
  120. await DeleteButton(accessPointName).ClickAsync();
  121. await DeleteConfirmButton.ClickAsync();
  122. await Assertions.Expect(Card(accessPointName))
  123. .Not.ToBeVisibleAsync();
  124. }
  125. public async Task RenameAsync(string accessPointName, string newName) {
  126. await RenameButton(accessPointName).ClickAsync();
  127. await RenameModalInput.FillAsync(newName);
  128. await RenameModalSubmit.ClickAsync();
  129. await page.WaitForURLAsync($"**/resources/hardware/{newName}");
  130. }
  131. public async Task CloneAsync(string accessPointName, string cloneName) {
  132. await CloneButton(accessPointName).ClickAsync();
  133. await CloneModalInput.FillAsync(cloneName);
  134. await CloneModalSubmit.ClickAsync();
  135. await page.WaitForURLAsync($"**/resources/hardware/{cloneName}");
  136. }
  137. private static string Sanitize(string value)
  138. => value.Replace(" ", "-");
  139. // -------------------------------------------------
  140. // Ports
  141. // -------------------------------------------------
  142. public async Task AddPortGroupAsync(
  143. string type,
  144. string speed,
  145. int count) {
  146. await Ports.AddPortGroupAsync(
  147. "accesspoint-ports",
  148. type,
  149. speed,
  150. count);
  151. }
  152. public async Task OpenConnectionFromPortAsync(int groupIndex, int portIndex) => await Ports.OpenConnectionFromPortAsync(_portsPrefix, groupIndex, portIndex);
  153. public async Task CreateConnectionAsync(
  154. string resourceA,
  155. string groupA,
  156. string portA,
  157. string resourceB,
  158. string groupB,
  159. string portB,
  160. string? label = null) {
  161. await Ports.CreateConnectionAsync(
  162. _portsPrefix,
  163. resourceA,
  164. groupA,
  165. portA,
  166. resourceB,
  167. groupB,
  168. portB,
  169. label);
  170. }
  171. public ILocator ConnectionLabelInput() => Ports.LabelInput(_portsPrefix);
  172. }