@gtkx/testing 0.20.0 → 1.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (216) hide show
  1. package/README.md +122 -55
  2. package/dist/act.d.ts +19 -0
  3. package/dist/act.d.ts.map +1 -0
  4. package/dist/act.js +48 -0
  5. package/dist/act.js.map +1 -0
  6. package/dist/bound-queries.d.ts +32 -0
  7. package/dist/bound-queries.d.ts.map +1 -0
  8. package/dist/bound-queries.js +2 -0
  9. package/dist/bound-queries.js.map +1 -0
  10. package/dist/build-queries.d.ts +16 -0
  11. package/dist/build-queries.d.ts.map +1 -0
  12. package/dist/build-queries.js +103 -0
  13. package/dist/build-queries.js.map +1 -0
  14. package/dist/cleanup-registry.d.ts +4 -0
  15. package/dist/cleanup-registry.d.ts.map +1 -0
  16. package/dist/cleanup-registry.js +11 -0
  17. package/dist/cleanup-registry.js.map +1 -0
  18. package/dist/config.d.ts +18 -51
  19. package/dist/config.d.ts.map +1 -1
  20. package/dist/config.js +9 -40
  21. package/dist/config.js.map +1 -1
  22. package/dist/editable.d.ts +7 -0
  23. package/dist/editable.d.ts.map +1 -0
  24. package/dist/editable.js +24 -0
  25. package/dist/editable.js.map +1 -0
  26. package/dist/errors.d.ts +29 -0
  27. package/dist/errors.d.ts.map +1 -0
  28. package/dist/errors.js +119 -0
  29. package/dist/errors.js.map +1 -0
  30. package/dist/fire-event.d.ts +7 -25
  31. package/dist/fire-event.d.ts.map +1 -1
  32. package/dist/fire-event.js +9 -29
  33. package/dist/fire-event.js.map +1 -1
  34. package/dist/frame-sync.d.ts +3 -0
  35. package/dist/frame-sync.d.ts.map +1 -0
  36. package/dist/frame-sync.js +30 -0
  37. package/dist/frame-sync.js.map +1 -0
  38. package/dist/index.d.ts +16 -11
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +10 -6
  41. package/dist/index.js.map +1 -1
  42. package/dist/matchers.d.ts +55 -0
  43. package/dist/matchers.d.ts.map +1 -0
  44. package/dist/matchers.js +103 -0
  45. package/dist/matchers.js.map +1 -0
  46. package/dist/pretty-widget.d.ts +21 -25
  47. package/dist/pretty-widget.d.ts.map +1 -1
  48. package/dist/pretty-widget.js +69 -115
  49. package/dist/pretty-widget.js.map +1 -1
  50. package/dist/queries.d.ts +130 -177
  51. package/dist/queries.d.ts.map +1 -1
  52. package/dist/queries.js +212 -325
  53. package/dist/queries.js.map +1 -1
  54. package/dist/register-test-hooks.d.ts +2 -0
  55. package/dist/register-test-hooks.d.ts.map +1 -0
  56. package/dist/register-test-hooks.js +15 -0
  57. package/dist/register-test-hooks.js.map +1 -0
  58. package/dist/render-hook.d.ts +14 -35
  59. package/dist/render-hook.d.ts.map +1 -1
  60. package/dist/render-hook.js +8 -45
  61. package/dist/render-hook.js.map +1 -1
  62. package/dist/render.d.ts +11 -41
  63. package/dist/render.d.ts.map +1 -1
  64. package/dist/render.js +129 -118
  65. package/dist/render.js.map +1 -1
  66. package/dist/role-helpers.d.ts +16 -51
  67. package/dist/role-helpers.d.ts.map +1 -1
  68. package/dist/role-helpers.js +39 -58
  69. package/dist/role-helpers.js.map +1 -1
  70. package/dist/screen.d.ts +6 -63
  71. package/dist/screen.d.ts.map +1 -1
  72. package/dist/screen.js +21 -109
  73. package/dist/screen.js.map +1 -1
  74. package/dist/screenshot.d.ts +20 -23
  75. package/dist/screenshot.d.ts.map +1 -1
  76. package/dist/screenshot.js +89 -48
  77. package/dist/screenshot.js.map +1 -1
  78. package/dist/suggestions.d.ts +22 -0
  79. package/dist/suggestions.d.ts.map +1 -0
  80. package/dist/suggestions.js +56 -0
  81. package/dist/suggestions.js.map +1 -0
  82. package/dist/traversal.d.ts +10 -8
  83. package/dist/traversal.d.ts.map +1 -1
  84. package/dist/traversal.js +28 -13
  85. package/dist/traversal.js.map +1 -1
  86. package/dist/types.d.ts +103 -172
  87. package/dist/types.d.ts.map +1 -1
  88. package/dist/types.js.map +1 -1
  89. package/dist/user-event/adjustment.d.ts +8 -0
  90. package/dist/user-event/adjustment.d.ts.map +1 -0
  91. package/dist/user-event/adjustment.js +33 -0
  92. package/dist/user-event/adjustment.js.map +1 -0
  93. package/dist/user-event/click.d.ts +7 -0
  94. package/dist/user-event/click.d.ts.map +1 -0
  95. package/dist/user-event/click.js +65 -0
  96. package/dist/user-event/click.js.map +1 -0
  97. package/dist/user-event/controller.d.ts +7 -0
  98. package/dist/user-event/controller.d.ts.map +1 -0
  99. package/dist/user-event/controller.js +28 -0
  100. package/dist/user-event/controller.js.map +1 -0
  101. package/dist/user-event/dispatch.d.ts +7 -0
  102. package/dist/user-event/dispatch.d.ts.map +1 -0
  103. package/dist/user-event/dispatch.js +10 -0
  104. package/dist/user-event/dispatch.js.map +1 -0
  105. package/dist/user-event/event-wrapper.d.ts +3 -0
  106. package/dist/user-event/event-wrapper.d.ts.map +1 -0
  107. package/dist/user-event/event-wrapper.js +48 -0
  108. package/dist/user-event/event-wrapper.js.map +1 -0
  109. package/dist/user-event/gesture.d.ts +31 -0
  110. package/dist/user-event/gesture.d.ts.map +1 -0
  111. package/dist/user-event/gesture.js +105 -0
  112. package/dist/user-event/gesture.js.map +1 -0
  113. package/dist/user-event/index.d.ts +44 -0
  114. package/dist/user-event/index.d.ts.map +1 -0
  115. package/dist/user-event/index.js +38 -0
  116. package/dist/user-event/index.js.map +1 -0
  117. package/dist/user-event/keyboard.d.ts +9 -0
  118. package/dist/user-event/keyboard.d.ts.map +1 -0
  119. package/dist/user-event/keyboard.js +173 -0
  120. package/dist/user-event/keyboard.js.map +1 -0
  121. package/dist/user-event/pointer.d.ts +6 -0
  122. package/dist/user-event/pointer.d.ts.map +1 -0
  123. package/dist/user-event/pointer.js +27 -0
  124. package/dist/user-event/pointer.js.map +1 -0
  125. package/dist/user-event/selection.d.ts +4 -0
  126. package/dist/user-event/selection.d.ts.map +1 -0
  127. package/dist/user-event/selection.js +106 -0
  128. package/dist/user-event/selection.js.map +1 -0
  129. package/dist/user-event/state.d.ts +6 -0
  130. package/dist/user-event/state.d.ts.map +1 -0
  131. package/dist/user-event/state.js +2 -0
  132. package/dist/user-event/state.js.map +1 -0
  133. package/dist/user-event/text.d.ts +17 -0
  134. package/dist/user-event/text.d.ts.map +1 -0
  135. package/dist/user-event/text.js +107 -0
  136. package/dist/user-event/text.js.map +1 -0
  137. package/dist/wait-for.d.ts +13 -32
  138. package/dist/wait-for.d.ts.map +1 -1
  139. package/dist/wait-for.js +62 -73
  140. package/dist/wait-for.js.map +1 -1
  141. package/dist/widget-accessible-properties.d.ts +33 -0
  142. package/dist/widget-accessible-properties.d.ts.map +1 -0
  143. package/dist/widget-accessible-properties.js +215 -0
  144. package/dist/widget-accessible-properties.js.map +1 -0
  145. package/dist/within.d.ts +9 -26
  146. package/dist/within.d.ts.map +1 -1
  147. package/dist/within.js +15 -25
  148. package/dist/within.js.map +1 -1
  149. package/package.json +21 -12
  150. package/src/act.ts +68 -0
  151. package/src/bound-queries.ts +36 -0
  152. package/src/build-queries.ts +185 -0
  153. package/src/cleanup-registry.ts +14 -0
  154. package/src/config.ts +28 -59
  155. package/src/editable.ts +30 -0
  156. package/src/errors.ts +130 -0
  157. package/src/fire-event.ts +11 -38
  158. package/src/frame-sync.ts +34 -0
  159. package/src/index.ts +60 -18
  160. package/src/matchers.ts +200 -0
  161. package/src/pretty-widget.ts +99 -138
  162. package/src/queries.ts +321 -425
  163. package/src/register-test-hooks.ts +16 -0
  164. package/src/render-hook.tsx +31 -44
  165. package/src/render.tsx +161 -149
  166. package/src/role-helpers.ts +47 -67
  167. package/src/screen.ts +21 -114
  168. package/src/screenshot.ts +104 -55
  169. package/src/suggestions.ts +87 -0
  170. package/src/traversal.ts +32 -18
  171. package/src/types.ts +115 -176
  172. package/src/user-event/adjustment.ts +49 -0
  173. package/src/user-event/click.ts +70 -0
  174. package/src/user-event/controller.ts +44 -0
  175. package/src/user-event/dispatch.ts +23 -0
  176. package/src/user-event/event-wrapper.ts +54 -0
  177. package/src/user-event/gesture.ts +154 -0
  178. package/src/user-event/index.ts +74 -0
  179. package/src/user-event/keyboard.ts +204 -0
  180. package/src/user-event/pointer.ts +34 -0
  181. package/src/user-event/selection.ts +122 -0
  182. package/src/user-event/state.ts +6 -0
  183. package/src/user-event/text.ts +137 -0
  184. package/src/wait-for.ts +79 -80
  185. package/src/widget-accessible-properties.ts +244 -0
  186. package/src/within.ts +26 -27
  187. package/dist/bind-queries.d.ts +0 -14
  188. package/dist/bind-queries.d.ts.map +0 -1
  189. package/dist/bind-queries.js +0 -29
  190. package/dist/bind-queries.js.map +0 -1
  191. package/dist/error-builder.d.ts +0 -28
  192. package/dist/error-builder.d.ts.map +0 -1
  193. package/dist/error-builder.js +0 -81
  194. package/dist/error-builder.js.map +0 -1
  195. package/dist/timing.d.ts +0 -18
  196. package/dist/timing.d.ts.map +0 -1
  197. package/dist/timing.js +0 -18
  198. package/dist/timing.js.map +0 -1
  199. package/dist/user-event.d.ts +0 -138
  200. package/dist/user-event.d.ts.map +0 -1
  201. package/dist/user-event.js +0 -411
  202. package/dist/user-event.js.map +0 -1
  203. package/dist/widget-text.d.ts +0 -69
  204. package/dist/widget-text.d.ts.map +0 -1
  205. package/dist/widget-text.js +0 -177
  206. package/dist/widget-text.js.map +0 -1
  207. package/dist/widget.d.ts +0 -3
  208. package/dist/widget.d.ts.map +0 -1
  209. package/dist/widget.js +0 -13
  210. package/dist/widget.js.map +0 -1
  211. package/src/bind-queries.ts +0 -52
  212. package/src/error-builder.ts +0 -102
  213. package/src/timing.ts +0 -17
  214. package/src/user-event.ts +0 -492
  215. package/src/widget-text.ts +0 -202
  216. package/src/widget.ts +0 -15
@@ -0,0 +1,106 @@
1
+ import * as Gtk from "@gtkx/gi/gtk";
2
+ import { formatRoleList } from "../role-helpers.js";
3
+ import { wrapEvent } from "./event-wrapper.js";
4
+ const SELECTABLE_ROLES = new Set([Gtk.AccessibleRole.COMBO_BOX, Gtk.AccessibleRole.LIST]);
5
+ const isSelectable = (widget) => {
6
+ return SELECTABLE_ROLES.has(widget.getAccessibleRole());
7
+ };
8
+ const selectListViewItems = (selectionModel, positions, exclusive) => {
9
+ if (positions.length === 0) {
10
+ selectionModel.unselectRange(0, selectionModel.getNItems());
11
+ return;
12
+ }
13
+ const [first] = positions;
14
+ if (exclusive && positions.length === 1 && first !== undefined) {
15
+ selectionModel.selectItem(first, true);
16
+ return;
17
+ }
18
+ const nItems = selectionModel.getNItems();
19
+ const selected = Gtk.Bitset.newEmpty();
20
+ const mask = Gtk.Bitset.newRange(0, nItems);
21
+ for (const pos of positions) {
22
+ selected.add(pos);
23
+ }
24
+ selectionModel.setSelection(selected, mask);
25
+ };
26
+ const isListView = (widget) => {
27
+ return widget instanceof Gtk.ListView || widget instanceof Gtk.GridView || widget instanceof Gtk.ColumnView;
28
+ };
29
+ const selectComboBoxOption = (widget, valueArray) => {
30
+ if (valueArray.length > 1) {
31
+ throw new Error("Cannot select multiple options: ComboBox only supports single selection");
32
+ }
33
+ const [selection] = valueArray;
34
+ if (selection === undefined)
35
+ return;
36
+ if (widget instanceof Gtk.DropDown) {
37
+ widget.setSelected(selection);
38
+ }
39
+ else if (widget instanceof Gtk.ComboBox) {
40
+ widget.setActive(selection);
41
+ }
42
+ };
43
+ const applyListBoxRows = (listBox, valueArray, select) => {
44
+ for (const value of valueArray) {
45
+ const row = listBox.getRowAtIndex(value);
46
+ if (!row)
47
+ continue;
48
+ if (select) {
49
+ listBox.selectRow(row);
50
+ row.activate();
51
+ }
52
+ else {
53
+ listBox.unselectRow(row);
54
+ }
55
+ }
56
+ };
57
+ const requireSelectionModel = (widget, verb) => {
58
+ const selectionModel = widget.getModel();
59
+ if (selectionModel === null) {
60
+ throw new Error(`Cannot ${verb} options: list view has no selection model`);
61
+ }
62
+ return selectionModel;
63
+ };
64
+ const selectInListView = (widget, valueArray) => {
65
+ const selectionModel = requireSelectionModel(widget, "select");
66
+ const isMultiSelection = selectionModel instanceof Gtk.MultiSelection;
67
+ selectListViewItems(selectionModel, valueArray, !isMultiSelection);
68
+ };
69
+ const selectByRole = (widget, valueArray) => {
70
+ if (!isSelectable(widget)) {
71
+ throw new Error(`Cannot select options: expected selectable widget (${formatRoleList(SELECTABLE_ROLES)})`);
72
+ }
73
+ const role = widget.getAccessibleRole();
74
+ if (role === Gtk.AccessibleRole.COMBO_BOX) {
75
+ selectComboBoxOption(widget, valueArray);
76
+ }
77
+ else if (widget instanceof Gtk.ListBox) {
78
+ applyListBoxRows(widget, valueArray, true);
79
+ }
80
+ };
81
+ export const selectOptions = (widget, values) => wrapEvent(widget, () => {
82
+ const valueArray = Array.isArray(values) ? values : [values];
83
+ if (isListView(widget)) {
84
+ selectInListView(widget, valueArray);
85
+ return;
86
+ }
87
+ selectByRole(widget, valueArray);
88
+ });
89
+ const deselectInListView = (widget, valueArray) => {
90
+ const selectionModel = requireSelectionModel(widget, "deselect");
91
+ for (const pos of valueArray) {
92
+ selectionModel.unselectItem(pos);
93
+ }
94
+ };
95
+ export const deselectOptions = (widget, values) => wrapEvent(widget, () => {
96
+ const valueArray = Array.isArray(values) ? values : [values];
97
+ if (isListView(widget)) {
98
+ deselectInListView(widget, valueArray);
99
+ return;
100
+ }
101
+ if (!(widget instanceof Gtk.ListBox)) {
102
+ throw new Error("Cannot deselect options: only ListBox supports deselection");
103
+ }
104
+ applyListBoxRows(widget, valueArray, false);
105
+ });
106
+ //# sourceMappingURL=selection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selection.js","sourceRoot":"","sources":["../../src/user-event/selection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAqB,CAAC,GAAG,CAAC,cAAc,CAAC,SAAS,EAAE,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;AAE9G,MAAM,YAAY,GAAG,CAAC,MAAkB,EAAW,EAAE;IACjD,OAAO,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC,CAAC;AAC5D,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,CAAC,cAAkC,EAAE,SAAmB,EAAE,SAAkB,EAAQ,EAAE;IAC9G,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,cAAc,CAAC,aAAa,CAAC,CAAC,EAAE,cAAc,CAAC,SAAS,EAAE,CAAC,CAAC;QAC5D,OAAO;IACX,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC;IAC1B,IAAI,SAAS,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC7D,cAAc,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACvC,OAAO;IACX,CAAC;IAED,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,EAAE,CAAC;IAC1C,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;IACvC,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAE5C,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;QAC1B,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACtB,CAAC;IAED,cAAc,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AAChD,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,MAAkB,EAA0D,EAAE;IAC9F,OAAO,MAAM,YAAY,GAAG,CAAC,QAAQ,IAAI,MAAM,YAAY,GAAG,CAAC,QAAQ,IAAI,MAAM,YAAY,GAAG,CAAC,UAAU,CAAC;AAChH,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,CAAC,MAAkB,EAAE,UAAoB,EAAQ,EAAE;IAC5E,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,yEAAyE,CAAC,CAAC;IAC/F,CAAC;IACD,MAAM,CAAC,SAAS,CAAC,GAAG,UAAU,CAAC;IAC/B,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO;IACpC,IAAI,MAAM,YAAY,GAAG,CAAC,QAAQ,EAAE,CAAC;QACjC,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC;SAAM,IAAI,MAAM,YAAY,GAAG,CAAC,QAAQ,EAAE,CAAC;QACxC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAChC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,CAAC,OAAoB,EAAE,UAAoB,EAAE,MAAe,EAAQ,EAAE;IAC3F,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,CAAC,GAAG;YAAE,SAAS;QACnB,IAAI,MAAM,EAAE,CAAC;YACT,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACvB,GAAG,CAAC,QAAQ,EAAE,CAAC;QACnB,CAAC;aAAM,CAAC;YACJ,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC;IACL,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,CAC1B,MAAoD,EACpD,IAAY,EACM,EAAE;IACpB,MAAM,cAAc,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;IACzC,IAAI,cAAc,KAAK,IAAI,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,UAAU,IAAI,4CAA4C,CAAC,CAAC;IAChF,CAAC;IACD,OAAO,cAAc,CAAC;AAC1B,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,CAAC,MAAoD,EAAE,UAAoB,EAAQ,EAAE;IAC1G,MAAM,cAAc,GAAG,qBAAqB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC/D,MAAM,gBAAgB,GAAG,cAAc,YAAY,GAAG,CAAC,cAAc,CAAC;IACtE,mBAAmB,CAAC,cAAc,EAAE,UAAU,EAAE,CAAC,gBAAgB,CAAC,CAAC;AACvE,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,CAAC,MAAkB,EAAE,UAAoB,EAAQ,EAAE;IACpE,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,sDAAsD,cAAc,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAC/G,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,CAAC,iBAAiB,EAAE,CAAC;IACxC,IAAI,IAAI,KAAK,GAAG,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC;QACxC,oBAAoB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC7C,CAAC;SAAM,IAAI,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,CAAC;QACvC,gBAAgB,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;IAC/C,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,MAAkB,EAAE,MAAyB,EAAiB,EAAE,CAC1F,SAAS,CAAC,MAAM,EAAE,GAAG,EAAE;IACnB,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC7D,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACrB,gBAAgB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QACrC,OAAO;IACX,CAAC;IACD,YAAY,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AACrC,CAAC,CAAC,CAAC;AAEP,MAAM,kBAAkB,GAAG,CAAC,MAAoD,EAAE,UAAoB,EAAQ,EAAE;IAC5G,MAAM,cAAc,GAAG,qBAAqB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACjE,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC3B,cAAc,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,MAAkB,EAAE,MAAyB,EAAiB,EAAE,CAC5F,SAAS,CAAC,MAAM,EAAE,GAAG,EAAE;IACnB,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC7D,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACrB,kBAAkB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QACvC,OAAO;IACX,CAAC;IACD,IAAI,CAAC,CAAC,MAAM,YAAY,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;IAClF,CAAC;IACD,gBAAgB,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC;AAChD,CAAC,CAAC,CAAC","sourcesContent":["import * as Gtk from \"@gtkx/gi/gtk\";\nimport { formatRoleList } from \"../role-helpers.js\";\nimport { wrapEvent } from \"./event-wrapper.js\";\n\nconst SELECTABLE_ROLES = new Set<Gtk.AccessibleRole>([Gtk.AccessibleRole.COMBO_BOX, Gtk.AccessibleRole.LIST]);\n\nconst isSelectable = (widget: Gtk.Widget): boolean => {\n return SELECTABLE_ROLES.has(widget.getAccessibleRole());\n};\n\nconst selectListViewItems = (selectionModel: Gtk.SelectionModel, positions: number[], exclusive: boolean): void => {\n if (positions.length === 0) {\n selectionModel.unselectRange(0, selectionModel.getNItems());\n return;\n }\n\n const [first] = positions;\n if (exclusive && positions.length === 1 && first !== undefined) {\n selectionModel.selectItem(first, true);\n return;\n }\n\n const nItems = selectionModel.getNItems();\n const selected = Gtk.Bitset.newEmpty();\n const mask = Gtk.Bitset.newRange(0, nItems);\n\n for (const pos of positions) {\n selected.add(pos);\n }\n\n selectionModel.setSelection(selected, mask);\n};\n\nconst isListView = (widget: Gtk.Widget): widget is Gtk.ListView | Gtk.GridView | Gtk.ColumnView => {\n return widget instanceof Gtk.ListView || widget instanceof Gtk.GridView || widget instanceof Gtk.ColumnView;\n};\n\nconst selectComboBoxOption = (widget: Gtk.Widget, valueArray: number[]): void => {\n if (valueArray.length > 1) {\n throw new Error(\"Cannot select multiple options: ComboBox only supports single selection\");\n }\n const [selection] = valueArray;\n if (selection === undefined) return;\n if (widget instanceof Gtk.DropDown) {\n widget.setSelected(selection);\n } else if (widget instanceof Gtk.ComboBox) {\n widget.setActive(selection);\n }\n};\n\nconst applyListBoxRows = (listBox: Gtk.ListBox, valueArray: number[], select: boolean): void => {\n for (const value of valueArray) {\n const row = listBox.getRowAtIndex(value);\n if (!row) continue;\n if (select) {\n listBox.selectRow(row);\n row.activate();\n } else {\n listBox.unselectRow(row);\n }\n }\n};\n\nconst requireSelectionModel = (\n widget: Gtk.ListView | Gtk.GridView | Gtk.ColumnView,\n verb: string,\n): Gtk.SelectionModel => {\n const selectionModel = widget.getModel();\n if (selectionModel === null) {\n throw new Error(`Cannot ${verb} options: list view has no selection model`);\n }\n return selectionModel;\n};\n\nconst selectInListView = (widget: Gtk.ListView | Gtk.GridView | Gtk.ColumnView, valueArray: number[]): void => {\n const selectionModel = requireSelectionModel(widget, \"select\");\n const isMultiSelection = selectionModel instanceof Gtk.MultiSelection;\n selectListViewItems(selectionModel, valueArray, !isMultiSelection);\n};\n\nconst selectByRole = (widget: Gtk.Widget, valueArray: number[]): void => {\n if (!isSelectable(widget)) {\n throw new Error(`Cannot select options: expected selectable widget (${formatRoleList(SELECTABLE_ROLES)})`);\n }\n\n const role = widget.getAccessibleRole();\n if (role === Gtk.AccessibleRole.COMBO_BOX) {\n selectComboBoxOption(widget, valueArray);\n } else if (widget instanceof Gtk.ListBox) {\n applyListBoxRows(widget, valueArray, true);\n }\n};\n\nexport const selectOptions = (widget: Gtk.Widget, values: number | number[]): Promise<void> =>\n wrapEvent(widget, () => {\n const valueArray = Array.isArray(values) ? values : [values];\n if (isListView(widget)) {\n selectInListView(widget, valueArray);\n return;\n }\n selectByRole(widget, valueArray);\n });\n\nconst deselectInListView = (widget: Gtk.ListView | Gtk.GridView | Gtk.ColumnView, valueArray: number[]): void => {\n const selectionModel = requireSelectionModel(widget, \"deselect\");\n for (const pos of valueArray) {\n selectionModel.unselectItem(pos);\n }\n};\n\nexport const deselectOptions = (widget: Gtk.Widget, values: number | number[]): Promise<void> =>\n wrapEvent(widget, () => {\n const valueArray = Array.isArray(values) ? values : [values];\n if (isListView(widget)) {\n deselectInListView(widget, valueArray);\n return;\n }\n if (!(widget instanceof Gtk.ListBox)) {\n throw new Error(\"Cannot deselect options: only ListBox supports deselection\");\n }\n applyListBoxRows(widget, valueArray, false);\n });\n"]}
@@ -0,0 +1,6 @@
1
+ export type UserEventState = {
2
+ modifierState: number;
3
+ mouseLeftDown: boolean;
4
+ };
5
+ export declare const createInitialState: () => UserEventState;
6
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/user-event/state.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF,eAAO,MAAM,kBAAkB,QAAO,cAA8D,CAAC"}
@@ -0,0 +1,2 @@
1
+ export const createInitialState = () => ({ modifierState: 0, mouseLeftDown: false });
2
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/user-event/state.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAmB,EAAE,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC","sourcesContent":["export type UserEventState = {\n modifierState: number;\n mouseLeftDown: boolean;\n};\n\nexport const createInitialState = (): UserEventState => ({ modifierState: 0, mouseLeftDown: false });\n"]}
@@ -0,0 +1,17 @@
1
+ import * as Gtk from "@gtkx/gi/gtk";
2
+ /** Options for {@link type}. */
3
+ export type TypeOptions = {
4
+ /** Do not focus the widget before typing. */
5
+ skipClick?: boolean | undefined;
6
+ /** Select from this offset before typing, replacing the selected range with the typed text. */
7
+ initialSelectionStart?: number | undefined;
8
+ /** End offset of the initial selection (defaults to the start offset). */
9
+ initialSelectionEnd?: number | undefined;
10
+ };
11
+ export declare const resetClipboard: () => void;
12
+ export declare const type: (widget: Gtk.Widget, text: string, options?: TypeOptions) => Promise<void>;
13
+ export declare const clear: (widget: Gtk.Widget) => Promise<void>;
14
+ export declare const copy: (widget: Gtk.Widget) => Promise<void>;
15
+ export declare const cut: (widget: Gtk.Widget) => Promise<void>;
16
+ export declare const paste: (widget: Gtk.Widget, text?: string) => Promise<void>;
17
+ //# sourceMappingURL=text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/user-event/text.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAKpC,gCAAgC;AAChC,MAAM,MAAM,WAAW,GAAG;IACtB,6CAA6C;IAC7C,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAChC,+FAA+F;IAC/F,qBAAqB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,0EAA0E;IAC1E,mBAAmB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5C,CAAC;AAkEF,eAAO,MAAM,cAAc,QAAO,IAEjC,CAAC;AAEF,eAAO,MAAM,IAAI,WAAY,GAAG,CAAC,MAAM,QAAQ,MAAM,YAAY,WAAW,KAAG,OAAO,CAAC,IAAI,CAYrF,CAAC;AAEP,eAAO,MAAM,KAAK,WAAY,GAAG,CAAC,MAAM,KAAG,OAAO,CAAC,IAAI,CAOjD,CAAC;AAEP,eAAO,MAAM,IAAI,WAAY,GAAG,CAAC,MAAM,KAAG,OAAO,CAAC,IAAI,CAOhD,CAAC;AAEP,eAAO,MAAM,GAAG,WAAY,GAAG,CAAC,MAAM,KAAG,OAAO,CAAC,IAAI,CAQ/C,CAAC;AAEP,eAAO,MAAM,KAAK,WAAkB,GAAG,CAAC,MAAM,SAAS,MAAM,KAAG,OAAO,CAAC,IAAI,CAS3E,CAAC"}
@@ -0,0 +1,107 @@
1
+ import * as Gdk from "@gtkx/gi/gdk";
2
+ import * as GObject from "@gtkx/gi/gobject";
3
+ import * as Gtk from "@gtkx/gi/gtk";
4
+ import { EDITABLE_ROLES, getEditableDelegate, isEditable } from "../editable.js";
5
+ import { formatRoleList } from "../role-helpers.js";
6
+ import { wrapEvent } from "./event-wrapper.js";
7
+ const EDITABLE_REQUIRED = `expected editable widget (${formatRoleList(EDITABLE_ROLES)})`;
8
+ const insertEditableText = (widget, text) => {
9
+ if (widget instanceof Gtk.TextView) {
10
+ widget.emit("insert-at-cursor", text);
11
+ return;
12
+ }
13
+ const target = getEditableDelegate(widget) ?? widget;
14
+ if (target instanceof Gtk.Text) {
15
+ target.emit("insert-at-cursor", text);
16
+ return;
17
+ }
18
+ const position = widget.getPosition();
19
+ const newPosition = widget.insertText(text, text.length, position);
20
+ widget.setPosition(newPosition);
21
+ };
22
+ const readSelection = (widget) => {
23
+ if (widget instanceof Gtk.TextView) {
24
+ const buffer = widget.getBuffer();
25
+ const [hasSelection, start, end] = buffer.getSelectionBounds();
26
+ return hasSelection ? buffer.getText(start, end, true) : "";
27
+ }
28
+ const [hasSelection, start, end] = widget.getSelectionBounds();
29
+ return hasSelection ? widget.getChars(start, end) : "";
30
+ };
31
+ const deleteSelection = (widget) => {
32
+ if (widget instanceof Gtk.TextView) {
33
+ widget.getBuffer().deleteSelection(false, true);
34
+ return;
35
+ }
36
+ widget.deleteSelection();
37
+ };
38
+ const setEditableText = (widget, text) => {
39
+ if (widget instanceof Gtk.TextView) {
40
+ widget.getBuffer().setText(text, text.length);
41
+ return;
42
+ }
43
+ widget.setText(text);
44
+ };
45
+ const applyInitialSelection = (widget, options) => {
46
+ if (options.initialSelectionStart === undefined)
47
+ return;
48
+ const start = options.initialSelectionStart;
49
+ const end = options.initialSelectionEnd ?? start;
50
+ if (widget instanceof Gtk.TextView) {
51
+ const buffer = widget.getBuffer();
52
+ buffer.selectRange(buffer.getIterAtOffset(start), buffer.getIterAtOffset(end));
53
+ if (end !== start)
54
+ deleteSelection(widget);
55
+ return;
56
+ }
57
+ widget.selectRegion(start, end);
58
+ if (end !== start)
59
+ widget.deleteSelection();
60
+ widget.setPosition(start);
61
+ };
62
+ const writeClipboardText = (widget, text) => {
63
+ const value = GObject.buildValue(GObject.TYPE_STRING, (v) => v.setString(text));
64
+ widget.getClipboard().set(value);
65
+ };
66
+ export const resetClipboard = () => {
67
+ Gdk.Display.getDefault()?.getClipboard().setContent(null);
68
+ };
69
+ export const type = (widget, text, options) => wrapEvent(widget, () => {
70
+ if (!isEditable(widget)) {
71
+ throw new Error(`Cannot type into element: ${EDITABLE_REQUIRED}`);
72
+ }
73
+ if (!options?.skipClick) {
74
+ widget.grabFocus();
75
+ }
76
+ applyInitialSelection(widget, options ?? {});
77
+ insertEditableText(widget, text);
78
+ });
79
+ export const clear = (widget) => wrapEvent(widget, () => {
80
+ if (!isEditable(widget)) {
81
+ throw new Error(`Cannot clear element: ${EDITABLE_REQUIRED}`);
82
+ }
83
+ setEditableText(widget, "");
84
+ });
85
+ export const copy = (widget) => wrapEvent(widget, () => {
86
+ if (!isEditable(widget)) {
87
+ throw new Error(`Cannot copy: ${EDITABLE_REQUIRED}`);
88
+ }
89
+ writeClipboardText(widget, readSelection(widget));
90
+ });
91
+ export const cut = (widget) => wrapEvent(widget, () => {
92
+ if (!isEditable(widget)) {
93
+ throw new Error(`Cannot cut: ${EDITABLE_REQUIRED}`);
94
+ }
95
+ writeClipboardText(widget, readSelection(widget));
96
+ deleteSelection(widget);
97
+ });
98
+ export const paste = async (widget, text) => {
99
+ if (!isEditable(widget)) {
100
+ throw new Error(`Cannot paste: ${EDITABLE_REQUIRED}`);
101
+ }
102
+ const content = text ?? (await widget.getClipboard().readTextAsync(null)) ?? "";
103
+ await wrapEvent(widget, () => {
104
+ insertEditableText(widget, content);
105
+ });
106
+ };
107
+ //# sourceMappingURL=text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/user-event/text.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Gdk from \"@gtkx/gi/gdk\";\nimport * as GObject from \"@gtkx/gi/gobject\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport { EDITABLE_ROLES, type EditableTarget, getEditableDelegate, isEditable } from \"../editable.js\";\nimport { formatRoleList } from \"../role-helpers.js\";\nimport { wrapEvent } from \"./event-wrapper.js\";\n\n/** Options for {@link type}. */\nexport type TypeOptions = {\n /** Do not focus the widget before typing. */\n skipClick?: boolean | undefined;\n /** Select from this offset before typing, replacing the selected range with the typed text. */\n initialSelectionStart?: number | undefined;\n /** End offset of the initial selection (defaults to the start offset). */\n initialSelectionEnd?: number | undefined;\n};\n\nconst EDITABLE_REQUIRED = `expected editable widget (${formatRoleList(EDITABLE_ROLES)})`;\n\nconst insertEditableText = (widget: EditableTarget, text: string): void => {\n if (widget instanceof Gtk.TextView) {\n widget.emit(\"insert-at-cursor\", text);\n return;\n }\n const target = getEditableDelegate(widget) ?? widget;\n if (target instanceof Gtk.Text) {\n target.emit(\"insert-at-cursor\", text);\n return;\n }\n\n const position = widget.getPosition();\n const newPosition = widget.insertText(text, text.length, position);\n widget.setPosition(newPosition);\n};\n\nconst readSelection = (widget: EditableTarget): string => {\n if (widget instanceof Gtk.TextView) {\n const buffer = widget.getBuffer();\n const [hasSelection, start, end] = buffer.getSelectionBounds();\n return hasSelection ? buffer.getText(start, end, true) : \"\";\n }\n const [hasSelection, start, end] = widget.getSelectionBounds();\n return hasSelection ? widget.getChars(start, end) : \"\";\n};\n\nconst deleteSelection = (widget: EditableTarget): void => {\n if (widget instanceof Gtk.TextView) {\n widget.getBuffer().deleteSelection(false, true);\n return;\n }\n widget.deleteSelection();\n};\n\nconst setEditableText = (widget: EditableTarget, text: string): void => {\n if (widget instanceof Gtk.TextView) {\n widget.getBuffer().setText(text, text.length);\n return;\n }\n widget.setText(text);\n};\n\nconst applyInitialSelection = (widget: EditableTarget, options: TypeOptions): void => {\n if (options.initialSelectionStart === undefined) return;\n const start = options.initialSelectionStart;\n const end = options.initialSelectionEnd ?? start;\n if (widget instanceof Gtk.TextView) {\n const buffer = widget.getBuffer();\n buffer.selectRange(buffer.getIterAtOffset(start), buffer.getIterAtOffset(end));\n if (end !== start) deleteSelection(widget);\n return;\n }\n widget.selectRegion(start, end);\n if (end !== start) widget.deleteSelection();\n widget.setPosition(start);\n};\n\nconst writeClipboardText = (widget: Gtk.Widget, text: string): void => {\n const value = GObject.buildValue(GObject.TYPE_STRING, (v) => v.setString(text));\n widget.getClipboard().set(value);\n};\n\nexport const resetClipboard = (): void => {\n Gdk.Display.getDefault()?.getClipboard().setContent(null);\n};\n\nexport const type = (widget: Gtk.Widget, text: string, options?: TypeOptions): Promise<void> =>\n wrapEvent(widget, () => {\n if (!isEditable(widget)) {\n throw new Error(`Cannot type into element: ${EDITABLE_REQUIRED}`);\n }\n\n if (!options?.skipClick) {\n widget.grabFocus();\n }\n\n applyInitialSelection(widget, options ?? {});\n insertEditableText(widget, text);\n });\n\nexport const clear = (widget: Gtk.Widget): Promise<void> =>\n wrapEvent(widget, () => {\n if (!isEditable(widget)) {\n throw new Error(`Cannot clear element: ${EDITABLE_REQUIRED}`);\n }\n\n setEditableText(widget, \"\");\n });\n\nexport const copy = (widget: Gtk.Widget): Promise<void> =>\n wrapEvent(widget, () => {\n if (!isEditable(widget)) {\n throw new Error(`Cannot copy: ${EDITABLE_REQUIRED}`);\n }\n\n writeClipboardText(widget, readSelection(widget));\n });\n\nexport const cut = (widget: Gtk.Widget): Promise<void> =>\n wrapEvent(widget, () => {\n if (!isEditable(widget)) {\n throw new Error(`Cannot cut: ${EDITABLE_REQUIRED}`);\n }\n\n writeClipboardText(widget, readSelection(widget));\n deleteSelection(widget);\n });\n\nexport const paste = async (widget: Gtk.Widget, text?: string): Promise<void> => {\n if (!isEditable(widget)) {\n throw new Error(`Cannot paste: ${EDITABLE_REQUIRED}`);\n }\n\n const content = text ?? (await widget.getClipboard().readTextAsync(null)) ?? \"\";\n await wrapEvent(widget, () => {\n insertEditableText(widget, content);\n });\n};\n"]}
@@ -1,42 +1,23 @@
1
- import type * as Gtk from "@gtkx/ffi/gtk";
1
+ import type * as Gtk from "@gtkx/gi/gtk";
2
2
  import type { WaitForOptions } from "./types.js";
3
3
  /**
4
- * Waits for a callback to succeed.
4
+ * Repeatedly invokes a callback until it succeeds without throwing or the
5
+ * timeout elapses, retrying on each rejection at a fixed interval.
5
6
  *
6
- * Repeatedly calls the callback until it returns without throwing,
7
- * or until the timeout is reached.
8
- *
9
- * @param callback - Function to execute repeatedly
10
- * @param options - Timeout and interval configuration
11
- * @returns Promise resolving to the callback's return value
12
- *
13
- * @example
14
- * ```tsx
15
- * import { waitFor } from "@gtkx/testing";
16
- *
17
- * await waitFor(() => {
18
- * expect(counter.value).toBe(5);
19
- * }, { timeout: 2000 });
20
- * ```
7
+ * @param callback The assertion or query to retry; its resolved value is returned.
8
+ * @param options Optional timeout, interval, and timeout error customization.
9
+ * @returns The callback's result once it succeeds.
21
10
  */
22
11
  export declare const waitFor: <T>(callback: () => T | Promise<T>, options?: WaitForOptions) => Promise<T>;
23
- type ElementOrCallback = Gtk.Widget | (() => Gtk.Widget | null);
12
+ type RemovalTarget = Gtk.Widget | Gtk.Widget[] | null;
13
+ type ElementOrCallback = Gtk.Widget | Gtk.Widget[] | (() => RemovalTarget);
24
14
  /**
25
- * Waits for an element to be removed from the widget tree.
26
- *
27
- * Polls until the element no longer has a parent or no longer exists.
28
- *
29
- * @param elementOrCallback - Element or function returning element to watch
30
- * @param options - Timeout and interval configuration
31
- *
32
- * @example
33
- * ```tsx
34
- * import { waitForElementToBeRemoved } from "@gtkx/testing";
15
+ * Waits until the given widget or widgets are detached from the tree. Rejects
16
+ * immediately if the target is already absent when called.
35
17
  *
36
- * const loader = await screen.findByRole(Gtk.AccessibleRole.PROGRESS_BAR);
37
- * await waitForElementToBeRemoved(loader);
38
- * // Loader is now gone
39
- * ```
18
+ * @param elementOrCallback The widget, array of widgets, or a function
19
+ * returning them to observe for removal.
20
+ * @param options Optional timeout and interval settings.
40
21
  */
41
22
  export declare const waitForElementToBeRemoved: (elementOrCallback: ElementOrCallback, options?: WaitForOptions) => Promise<void>;
42
23
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"wait-for.d.ts","sourceRoot":"","sources":["../src/wait-for.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,GAAG,MAAM,eAAe,CAAC;AAG1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAIjD;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,OAAO,GAAU,CAAC,EAAE,UAAU,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,UAAU,cAAc,KAAG,OAAO,CAAC,CAAC,CAoBpG,CAAC;AAEF,KAAK,iBAAiB,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,MAAM,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;AAoBhE;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,yBAAyB,GAClC,mBAAmB,iBAAiB,EACpC,UAAU,cAAc,KACzB,OAAO,CAAC,IAAI,CA0Bd,CAAC"}
1
+ {"version":3,"file":"wait-for.d.ts","sourceRoot":"","sources":["../src/wait-for.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,GAAG,MAAM,cAAc,CAAC;AAIzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAYjD;;;;;;;GAOG;AACH,eAAO,MAAM,OAAO,GAAI,CAAC,YAAY,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,YAAY,cAAc,KAAG,OAAO,CAAC,CAAC,CA+B9F,CAAC;AAEF,KAAK,aAAa,GAAG,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC;AAEtD,KAAK,iBAAiB,GAAG,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,aAAa,CAAC,CAAC;AA4B3E;;;;;;;GAOG;AACH,eAAO,MAAM,yBAAyB,sBACf,iBAAiB,YAC1B,cAAc,KACzB,OAAO,CAAC,IAAI,CAed,CAAC"}
package/dist/wait-for.js CHANGED
@@ -1,98 +1,87 @@
1
+ import { runWithActEnvironment } from "./act.js";
1
2
  import { getConfig } from "./config.js";
2
- import { buildTimeoutError } from "./error-builder.js";
3
+ import { timeoutError } from "./errors.js";
3
4
  const DEFAULT_INTERVAL = 50;
5
+ const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
6
+ const copyStackTrace = (target, source) => {
7
+ if (source.stack) {
8
+ target.stack = source.stack.replace(source.message, target.message);
9
+ }
10
+ };
4
11
  /**
5
- * Waits for a callback to succeed.
6
- *
7
- * Repeatedly calls the callback until it returns without throwing,
8
- * or until the timeout is reached.
9
- *
10
- * @param callback - Function to execute repeatedly
11
- * @param options - Timeout and interval configuration
12
- * @returns Promise resolving to the callback's return value
13
- *
14
- * @example
15
- * ```tsx
16
- * import { waitFor } from "@gtkx/testing";
12
+ * Repeatedly invokes a callback until it succeeds without throwing or the
13
+ * timeout elapses, retrying on each rejection at a fixed interval.
17
14
  *
18
- * await waitFor(() => {
19
- * expect(counter.value).toBe(5);
20
- * }, { timeout: 2000 });
21
- * ```
15
+ * @param callback The assertion or query to retry; its resolved value is returned.
16
+ * @param options Optional timeout, interval, and timeout error customization.
17
+ * @returns The callback's result once it succeeds.
22
18
  */
23
- export const waitFor = async (callback, options) => {
24
- const config = getConfig();
25
- const { timeout = config.asyncUtilTimeout, interval = DEFAULT_INTERVAL, onTimeout } = options ?? {};
26
- const startTime = Date.now();
27
- let lastError = null;
28
- while (Date.now() - startTime < timeout) {
29
- try {
30
- return await callback();
31
- }
32
- catch (error) {
33
- lastError = error;
34
- await new Promise((resolve) => setTimeout(resolve, interval));
35
- }
19
+ export const waitFor = (callback, options) => {
20
+ if (typeof callback !== "function") {
21
+ throw new TypeError("Received `callback` arg must be a function");
36
22
  }
37
- const timeoutError = buildTimeoutError(timeout, lastError);
38
- if (onTimeout) {
39
- throw onTimeout(timeoutError);
40
- }
41
- throw timeoutError;
23
+ const stackTraceError = options?.stackTraceError ?? new Error("STACK_TRACE_MESSAGE");
24
+ return Promise.resolve(runWithActEnvironment(false, async () => {
25
+ const config = getConfig();
26
+ const { timeout = config.asyncUtilTimeout, interval = DEFAULT_INTERVAL, onTimeout } = options ?? {};
27
+ const startTime = Date.now();
28
+ let lastError = null;
29
+ while (Date.now() - startTime < timeout) {
30
+ try {
31
+ const result = await callback();
32
+ await delay(0);
33
+ return result;
34
+ }
35
+ catch (error) {
36
+ lastError = error;
37
+ await delay(interval);
38
+ }
39
+ }
40
+ const error = timeoutError(timeout, lastError);
41
+ const finalError = onTimeout ? onTimeout(error) : error;
42
+ copyStackTrace(finalError, stackTraceError);
43
+ throw finalError;
44
+ }));
42
45
  };
43
- const getElement = (elementOrCallback) => {
46
+ const getTarget = (elementOrCallback) => {
44
47
  if (typeof elementOrCallback === "function") {
45
48
  return elementOrCallback();
46
49
  }
47
50
  return elementOrCallback;
48
51
  };
49
- const isElementRemoved = (element) => {
50
- if (element === null)
52
+ const isWidgetRemoved = (widget) => {
53
+ if (widget === null)
51
54
  return true;
52
55
  try {
53
- const parent = element.getParent();
54
- return parent === null;
56
+ return widget.getRoot() === null;
55
57
  }
56
58
  catch {
57
59
  return true;
58
60
  }
59
61
  };
62
+ const isTargetRemoved = (target) => {
63
+ if (Array.isArray(target)) {
64
+ return target.length === 0 || target.every(isWidgetRemoved);
65
+ }
66
+ return isWidgetRemoved(target);
67
+ };
68
+ const ELEMENT_NOT_REMOVED = new Error("Element not yet removed");
60
69
  /**
61
- * Waits for an element to be removed from the widget tree.
62
- *
63
- * Polls until the element no longer has a parent or no longer exists.
64
- *
65
- * @param elementOrCallback - Element or function returning element to watch
66
- * @param options - Timeout and interval configuration
70
+ * Waits until the given widget or widgets are detached from the tree. Rejects
71
+ * immediately if the target is already absent when called.
67
72
  *
68
- * @example
69
- * ```tsx
70
- * import { waitForElementToBeRemoved } from "@gtkx/testing";
71
- *
72
- * const loader = await screen.findByRole(Gtk.AccessibleRole.PROGRESS_BAR);
73
- * await waitForElementToBeRemoved(loader);
74
- * // Loader is now gone
75
- * ```
73
+ * @param elementOrCallback The widget, array of widgets, or a function
74
+ * returning them to observe for removal.
75
+ * @param options Optional timeout and interval settings.
76
76
  */
77
- export const waitForElementToBeRemoved = async (elementOrCallback, options) => {
78
- const config = getConfig();
79
- const { timeout = config.asyncUtilTimeout, interval = DEFAULT_INTERVAL, onTimeout } = options ?? {};
80
- const initialElement = getElement(elementOrCallback);
81
- if (initialElement === null || isElementRemoved(initialElement)) {
82
- throw new Error("Element already removed: waitForElementToBeRemoved requires the element to be present initially");
83
- }
84
- const startTime = Date.now();
85
- while (Date.now() - startTime < timeout) {
86
- const element = getElement(elementOrCallback);
87
- if (isElementRemoved(element)) {
88
- return;
89
- }
90
- await new Promise((resolve) => setTimeout(resolve, interval));
91
- }
92
- const timeoutError = new Error(`Timed out after ${timeout}ms waiting for element to be removed.`);
93
- if (onTimeout) {
94
- throw onTimeout(timeoutError);
77
+ export const waitForElementToBeRemoved = (elementOrCallback, options) => {
78
+ const stackTraceError = new Error("STACK_TRACE_MESSAGE");
79
+ if (isTargetRemoved(getTarget(elementOrCallback))) {
80
+ return Promise.reject(new Error("Element already removed: waitForElementToBeRemoved requires the element to be present initially"));
95
81
  }
96
- throw timeoutError;
82
+ return waitFor(() => {
83
+ if (!isTargetRemoved(getTarget(elementOrCallback)))
84
+ throw ELEMENT_NOT_REMOVED;
85
+ }, { ...options, stackTraceError });
97
86
  };
98
87
  //# sourceMappingURL=wait-for.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"wait-for.js","sourceRoot":"","sources":["../src/wait-for.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"wait-for.js","sourceRoot":"","sources":["../src/wait-for.ts"],"names":[],"mappings":"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","sourcesContent":["import type * as Gtk from \"@gtkx/gi/gtk\";\nimport { runWithActEnvironment } from \"./act.js\";\nimport { getConfig } from \"./config.js\";\nimport { timeoutError } from \"./errors.js\";\nimport type { WaitForOptions } from \"./types.js\";\n\nconst DEFAULT_INTERVAL = 50;\n\nconst delay = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\nconst copyStackTrace = (target: Error, source: Error): void => {\n if (source.stack) {\n target.stack = source.stack.replace(source.message, target.message);\n }\n};\n\n/**\n * Repeatedly invokes a callback until it succeeds without throwing or the\n * timeout elapses, retrying on each rejection at a fixed interval.\n *\n * @param callback The assertion or query to retry; its resolved value is returned.\n * @param options Optional timeout, interval, and timeout error customization.\n * @returns The callback's result once it succeeds.\n */\nexport const waitFor = <T>(callback: () => T | Promise<T>, options?: WaitForOptions): Promise<T> => {\n if (typeof callback !== \"function\") {\n throw new TypeError(\"Received `callback` arg must be a function\");\n }\n\n const stackTraceError = options?.stackTraceError ?? new Error(\"STACK_TRACE_MESSAGE\");\n\n return Promise.resolve(\n runWithActEnvironment(false, async () => {\n const config = getConfig();\n const { timeout = config.asyncUtilTimeout, interval = DEFAULT_INTERVAL, onTimeout } = options ?? {};\n const startTime = Date.now();\n let lastError: Error | null = null;\n\n while (Date.now() - startTime < timeout) {\n try {\n const result = await callback();\n await delay(0);\n return result;\n } catch (error) {\n lastError = error as Error;\n await delay(interval);\n }\n }\n\n const error = timeoutError(timeout, lastError);\n const finalError = onTimeout ? onTimeout(error) : error;\n copyStackTrace(finalError, stackTraceError);\n throw finalError;\n }),\n );\n};\n\ntype RemovalTarget = Gtk.Widget | Gtk.Widget[] | null;\n\ntype ElementOrCallback = Gtk.Widget | Gtk.Widget[] | (() => RemovalTarget);\n\nconst getTarget = (elementOrCallback: ElementOrCallback): RemovalTarget => {\n if (typeof elementOrCallback === \"function\") {\n return elementOrCallback();\n }\n return elementOrCallback;\n};\n\nconst isWidgetRemoved = (widget: Gtk.Widget | null): boolean => {\n if (widget === null) return true;\n\n try {\n return widget.getRoot() === null;\n } catch {\n return true;\n }\n};\n\nconst isTargetRemoved = (target: RemovalTarget): boolean => {\n if (Array.isArray(target)) {\n return target.length === 0 || target.every(isWidgetRemoved);\n }\n return isWidgetRemoved(target);\n};\n\nconst ELEMENT_NOT_REMOVED = new Error(\"Element not yet removed\");\n\n/**\n * Waits until the given widget or widgets are detached from the tree. Rejects\n * immediately if the target is already absent when called.\n *\n * @param elementOrCallback The widget, array of widgets, or a function\n * returning them to observe for removal.\n * @param options Optional timeout and interval settings.\n */\nexport const waitForElementToBeRemoved = (\n elementOrCallback: ElementOrCallback,\n options?: WaitForOptions,\n): Promise<void> => {\n const stackTraceError = new Error(\"STACK_TRACE_MESSAGE\");\n if (isTargetRemoved(getTarget(elementOrCallback))) {\n return Promise.reject(\n new Error(\n \"Element already removed: waitForElementToBeRemoved requires the element to be present initially\",\n ),\n );\n }\n return waitFor(\n () => {\n if (!isTargetRemoved(getTarget(elementOrCallback))) throw ELEMENT_NOT_REMOVED;\n },\n { ...options, stackTraceError },\n );\n};\n"]}
@@ -0,0 +1,33 @@
1
+ import * as Gtk from "@gtkx/gi/gtk";
2
+ /**
3
+ * Returns a widget's own text by trying its label, text, and title getters in
4
+ * order, or null when none produce a value.
5
+ *
6
+ * @param widget The widget to read text from.
7
+ */
8
+ export declare const getWidgetNodeText: (widget: Gtk.Widget) => string | null;
9
+ export declare const getWidgetLabelText: (widget: Gtk.Widget) => string | null;
10
+ export declare const getWidgetAccessibleName: (widget: Gtk.Widget) => string | null;
11
+ export declare const getWidgetName: (widget: Gtk.Widget) => string | null;
12
+ export declare const getWidgetPlaceholderText: (widget: Gtk.Widget) => string | null;
13
+ export declare const getWidgetDisplayValue: (widget: Gtk.Widget) => string | null;
14
+ export declare const getWidgetCheckedState: (widget: Gtk.Widget) => boolean | null;
15
+ export declare const getWidgetPressedState: (widget: Gtk.Widget) => boolean | null;
16
+ export declare const getWidgetExpandedState: (widget: Gtk.Widget) => boolean | null;
17
+ export declare const getWidgetSelectedState: (widget: Gtk.Widget) => boolean | null;
18
+ export declare const getWidgetLevel: (widget: Gtk.Widget) => number | null;
19
+ export declare const getWidgetInvalidState: (widget: Gtk.Widget) => Gtk.AccessibleInvalidState | null;
20
+ export declare const getWidgetErrorMessage: (widget: Gtk.Widget) => Gtk.Widget[] | null;
21
+ export declare const getWidgetBusyState: (widget: Gtk.Widget) => boolean | null;
22
+ export declare const getWidgetDescription: (widget: Gtk.Widget) => string | null;
23
+ export type WidgetValue = {
24
+ now: number | null;
25
+ min: number | null;
26
+ max: number | null;
27
+ text: string | null;
28
+ };
29
+ export declare const getWidgetValue: (widget: Gtk.Widget) => WidgetValue;
30
+ export declare const getWidgetOwnLabel: (widget: Gtk.Widget) => string | null;
31
+ export declare const getWidgetLabelledByText: (widget: Gtk.Widget) => string | null;
32
+ export declare const isInaccessible: (widget: Gtk.Widget) => boolean;
33
+ //# sourceMappingURL=widget-accessible-properties.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widget-accessible-properties.d.ts","sourceRoot":"","sources":["../src/widget-accessible-properties.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAmCpC;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,WAAY,GAAG,CAAC,MAAM,KAAG,MAAM,GAAG,IAM/D,CAAC;AAwBF,eAAO,MAAM,kBAAkB,WAAY,GAAG,CAAC,MAAM,KAAG,MAAM,GAAG,IAGhE,CAAC;AAEF,eAAO,MAAM,uBAAuB,WAAY,GAAG,CAAC,MAAM,KAAG,MAAM,GAAG,IAsBrE,CAAC;AAEF,eAAO,MAAM,aAAa,WAAY,GAAG,CAAC,MAAM,KAAG,MAAM,GAAG,IAE3D,CAAC;AAEF,eAAO,MAAM,wBAAwB,WAAY,GAAG,CAAC,MAAM,KAAG,MAAM,GAAG,IAMtE,CAAC;AAEF,eAAO,MAAM,qBAAqB,WAAY,GAAG,CAAC,MAAM,KAAG,MAAM,GAAG,IAMnE,CAAC;AAEF,eAAO,MAAM,qBAAqB,WAAY,GAAG,CAAC,MAAM,KAAG,OAAO,GAAG,IAOpE,CAAC;AAEF,eAAO,MAAM,qBAAqB,WAAY,GAAG,CAAC,MAAM,KAAG,OAAO,GAAG,IAGpE,CAAC;AAEF,eAAO,MAAM,sBAAsB,WAAY,GAAG,CAAC,MAAM,KAAG,OAAO,GAAG,IAUrE,CAAC;AAEF,eAAO,MAAM,sBAAsB,WAAY,GAAG,CAAC,MAAM,KAAG,OAAO,GAAG,IAUrE,CAAC;AAEF,eAAO,MAAM,cAAc,WAAY,GAAG,CAAC,MAAM,KAAG,MAAM,GAAG,IAE5D,CAAC;AAEF,eAAO,MAAM,qBAAqB,WAAY,GAAG,CAAC,MAAM,KAAG,GAAG,CAAC,sBAAsB,GAAG,IAEvF,CAAC;AAEF,eAAO,MAAM,qBAAqB,WAAY,GAAG,CAAC,MAAM,KAAG,GAAG,CAAC,MAAM,EAAE,GAAG,IAGzE,CAAC;AAEF,eAAO,MAAM,kBAAkB,WAAY,GAAG,CAAC,MAAM,KAAG,OAAO,GAAG,IAEjE,CAAC;AAEF,eAAO,MAAM,oBAAoB,WAAY,GAAG,CAAC,MAAM,KAAG,MAAM,GAAG,IAElE,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACtB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAsBF,eAAO,MAAM,cAAc,WAAY,GAAG,CAAC,MAAM,KAAG,WAUnD,CAAC;AAEF,eAAO,MAAM,iBAAiB,WAAY,GAAG,CAAC,MAAM,KAAG,MAAM,GAAG,IAE/D,CAAC;AAEF,eAAO,MAAM,uBAAuB,WAAY,GAAG,CAAC,MAAM,KAAG,MAAM,GAAG,IAWrE,CAAC;AAEF,eAAO,MAAM,cAAc,WAAY,GAAG,CAAC,MAAM,KAAG,OAQnD,CAAC"}