@gtkx/testing 1.0.0-rc.3 → 1.0.0-rc.4

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 (103) hide show
  1. package/README.md +4 -5
  2. package/dist/act.d.ts +2 -0
  3. package/dist/act.d.ts.map +1 -1
  4. package/dist/act.js.map +1 -1
  5. package/dist/build-queries.d.ts.map +1 -1
  6. package/dist/build-queries.js +18 -7
  7. package/dist/build-queries.js.map +1 -1
  8. package/dist/config.d.ts +1 -0
  9. package/dist/config.d.ts.map +1 -1
  10. package/dist/config.js +3 -3
  11. package/dist/config.js.map +1 -1
  12. package/dist/errors.js +2 -2
  13. package/dist/errors.js.map +1 -1
  14. package/dist/matchers.d.ts +44 -0
  15. package/dist/matchers.d.ts.map +1 -1
  16. package/dist/matchers.js.map +1 -1
  17. package/dist/pretty-widget.d.ts +2 -1
  18. package/dist/pretty-widget.d.ts.map +1 -1
  19. package/dist/pretty-widget.js +3 -3
  20. package/dist/pretty-widget.js.map +1 -1
  21. package/dist/queries.d.ts +1 -0
  22. package/dist/queries.d.ts.map +1 -1
  23. package/dist/queries.js.map +1 -1
  24. package/dist/render.js +2 -2
  25. package/dist/render.js.map +1 -1
  26. package/dist/suggestions.d.ts +3 -0
  27. package/dist/suggestions.d.ts.map +1 -1
  28. package/dist/suggestions.js.map +1 -1
  29. package/dist/traversal.d.ts +5 -0
  30. package/dist/traversal.d.ts.map +1 -1
  31. package/dist/traversal.js +1 -0
  32. package/dist/traversal.js.map +1 -1
  33. package/dist/types.d.ts +43 -5
  34. package/dist/types.d.ts.map +1 -1
  35. package/dist/types.js.map +1 -1
  36. package/dist/user-event/adjustment.d.ts +13 -0
  37. package/dist/user-event/adjustment.d.ts.map +1 -1
  38. package/dist/user-event/adjustment.js +11 -0
  39. package/dist/user-event/adjustment.js.map +1 -1
  40. package/dist/user-event/click.d.ts +7 -0
  41. package/dist/user-event/click.d.ts.map +1 -1
  42. package/dist/user-event/click.js +7 -0
  43. package/dist/user-event/click.js.map +1 -1
  44. package/dist/user-event/controller.d.ts +29 -0
  45. package/dist/user-event/controller.d.ts.map +1 -1
  46. package/dist/user-event/controller.js +28 -0
  47. package/dist/user-event/controller.js.map +1 -1
  48. package/dist/user-event/gesture.d.ts +51 -0
  49. package/dist/user-event/gesture.d.ts.map +1 -1
  50. package/dist/user-event/gesture.js +47 -4
  51. package/dist/user-event/gesture.js.map +1 -1
  52. package/dist/user-event/index.d.ts +27 -0
  53. package/dist/user-event/index.d.ts.map +1 -1
  54. package/dist/user-event/index.js.map +1 -1
  55. package/dist/user-event/keyboard.d.ts +4 -2
  56. package/dist/user-event/keyboard.d.ts.map +1 -1
  57. package/dist/user-event/keyboard.js +13 -12
  58. package/dist/user-event/keyboard.js.map +1 -1
  59. package/dist/user-event/pointer.js +5 -5
  60. package/dist/user-event/pointer.js.map +1 -1
  61. package/dist/user-event/selection.d.ts +15 -0
  62. package/dist/user-event/selection.d.ts.map +1 -1
  63. package/dist/user-event/selection.js +15 -0
  64. package/dist/user-event/selection.js.map +1 -1
  65. package/dist/user-event/state.d.ts +1 -1
  66. package/dist/user-event/state.d.ts.map +1 -1
  67. package/dist/user-event/state.js +1 -1
  68. package/dist/user-event/state.js.map +1 -1
  69. package/dist/user-event/text.d.ts +30 -3
  70. package/dist/user-event/text.d.ts.map +1 -1
  71. package/dist/user-event/text.js +28 -1
  72. package/dist/user-event/text.js.map +1 -1
  73. package/dist/wait-for.d.ts +2 -0
  74. package/dist/wait-for.d.ts.map +1 -1
  75. package/dist/wait-for.js.map +1 -1
  76. package/dist/widget-accessible-properties.d.ts +17 -1
  77. package/dist/widget-accessible-properties.d.ts.map +1 -1
  78. package/dist/widget-accessible-properties.js +17 -0
  79. package/dist/widget-accessible-properties.js.map +1 -1
  80. package/package.json +7 -7
  81. package/src/act.ts +2 -0
  82. package/src/build-queries.ts +20 -8
  83. package/src/config.ts +4 -3
  84. package/src/errors.ts +2 -2
  85. package/src/matchers.ts +44 -0
  86. package/src/pretty-widget.ts +5 -4
  87. package/src/queries.ts +1 -0
  88. package/src/render.tsx +2 -2
  89. package/src/suggestions.ts +3 -0
  90. package/src/traversal.ts +5 -0
  91. package/src/types.ts +43 -5
  92. package/src/user-event/adjustment.ts +13 -0
  93. package/src/user-event/click.ts +7 -0
  94. package/src/user-event/controller.ts +29 -0
  95. package/src/user-event/gesture.ts +57 -6
  96. package/src/user-event/index.ts +27 -0
  97. package/src/user-event/keyboard.ts +18 -16
  98. package/src/user-event/pointer.ts +5 -5
  99. package/src/user-event/selection.ts +15 -0
  100. package/src/user-event/state.ts +2 -2
  101. package/src/user-event/text.ts +31 -4
  102. package/src/wait-for.ts +2 -0
  103. package/src/widget-accessible-properties.ts +17 -1
@@ -9,13 +9,17 @@ type DropContent = string | number | boolean | GObject.Value;
9
9
 
10
10
  /** Options for a drop: the drop coordinates within the target. */
11
11
  type DropOptions = {
12
+ /** Horizontal drop coordinate within the target, in pixels. */
12
13
  x?: number;
14
+ /** Vertical drop coordinate within the target, in pixels. */
13
15
  y?: number;
14
16
  };
15
17
 
16
18
  /** A drag offset relative to the drag start point. */
17
19
  type DragOffset = {
20
+ /** Horizontal distance from the drag start point, in pixels. */
18
21
  x: number;
22
+ /** Vertical distance from the drag start point, in pixels. */
19
23
  y: number;
20
24
  };
21
25
 
@@ -24,9 +28,13 @@ type DragOffset = {
24
28
  * explicit intermediate offsets emitted before the final one.
25
29
  */
26
30
  type DragOptions = {
31
+ /** Horizontal coordinate the drag begins at; defaults to 0. */
27
32
  startX?: number;
33
+ /** Vertical coordinate the drag begins at; defaults to 0. */
28
34
  startY?: number;
35
+ /** Number of evenly interpolated drag updates, the last of which is the requested offset; defaults to 2. */
29
36
  steps?: number;
37
+ /** Explicit intermediate offsets emitted before the requested one, used instead of `steps`. */
30
38
  offsets?: DragOffset[];
31
39
  };
32
40
 
@@ -37,8 +45,8 @@ type DragInstancePatch = {
37
45
 
38
46
  type SavedDragState = {
39
47
  instance: DragInstancePatch;
40
- ownsStartPoint: boolean;
41
- ownsOffset: boolean;
48
+ hasOwnStartPoint: boolean;
49
+ hasOwnOffset: boolean;
42
50
  previousStartPoint: DragInstancePatch["getStartPoint"];
43
51
  previousOffset: DragInstancePatch["getOffset"];
44
52
  };
@@ -65,32 +73,56 @@ const buildDropValue = (content: DropContent): GObject.Value => {
65
73
  });
66
74
  };
67
75
 
76
+ /** Emits `enter` at the widget's origin on its motion controllers, adding one when it has none. */
68
77
  const hover = (widget: Gtk.Widget): Promise<void> =>
69
78
  dispatchOnOrCreateControllers(widget, Gtk.EventControllerMotion, (controller) => {
70
79
  controller.emit("enter", 0, 0);
71
80
  });
72
81
 
82
+ /** Emits `leave` on the widget's motion controllers, adding one when it has none. */
73
83
  const unhover = (widget: Gtk.Widget): Promise<void> =>
74
84
  dispatchOnOrCreateControllers(widget, Gtk.EventControllerMotion, (controller) => {
75
85
  controller.emit("leave");
76
86
  });
77
87
 
88
+ /**
89
+ * Emits `angle-changed` on the widget's rotate gestures.
90
+ *
91
+ * @param angle Current angle, in radians.
92
+ * @param deltaAngle Difference from the angle the gesture started at; defaults to `angle`.
93
+ * @throws When the widget has no Gtk.GestureRotate.
94
+ */
78
95
  const rotate = (widget: Gtk.Widget, angle: number, deltaAngle: number = angle): Promise<void> =>
79
96
  dispatchOnControllers(widget, Gtk.GestureRotate, (controller) => {
80
97
  controller.emit("angle-changed", angle, deltaAngle);
81
98
  },
82
99
  );
83
100
 
101
+ /**
102
+ * Emits `scale-changed` with the given scale delta on the widget's zoom gestures.
103
+ *
104
+ * @throws When the widget has no Gtk.GestureZoom.
105
+ */
84
106
  const zoom = (widget: Gtk.Widget, scale: number): Promise<void> =>
85
107
  dispatchOnControllers(widget, Gtk.GestureZoom, (controller) => {
86
108
  controller.emit("scale-changed", scale);
87
109
  });
88
110
 
111
+ /**
112
+ * Emits `swipe` with the given per-axis velocity, in pixels per second, on the widget's swipe gestures.
113
+ *
114
+ * @throws When the widget has no Gtk.GestureSwipe.
115
+ */
89
116
  const swipe = (widget: Gtk.Widget, velocityX: number, velocityY: number): Promise<void> =>
90
117
  dispatchOnControllers(widget, Gtk.GestureSwipe, (controller) => {
91
118
  controller.emit("swipe", velocityX, velocityY);
92
119
  });
93
120
 
121
+ /**
122
+ * Emits `pressed` at the given point in widget coordinates on the widget's long-press gestures.
123
+ *
124
+ * @throws When the widget has no Gtk.GestureLongPress.
125
+ */
94
126
  const longPress = (widget: Gtk.Widget, x = 0, y = 0): Promise<void> =>
95
127
  dispatchOnControllers(widget, Gtk.GestureLongPress, (controller) => {
96
128
  controller.emit("pressed", x, y);
@@ -99,13 +131,13 @@ const longPress = (widget: Gtk.Widget, x = 0, y = 0): Promise<void> =>
99
131
  const restoreDragState = (saved: SavedDragState): void => {
100
132
  const { instance } = saved;
101
133
 
102
- if (saved.ownsStartPoint) {
134
+ if (saved.hasOwnStartPoint) {
103
135
  instance.getStartPoint = saved.previousStartPoint;
104
136
  } else {
105
137
  delete instance.getStartPoint;
106
138
  }
107
139
 
108
- if (saved.ownsOffset) {
140
+ if (saved.hasOwnOffset) {
109
141
  instance.getOffset = saved.previousOffset;
110
142
  } else {
111
143
  delete instance.getOffset;
@@ -117,8 +149,8 @@ const patchDragState = (controller: Gtk.GestureDrag, start: DragOffset, offset:
117
149
 
118
150
  const saved: SavedDragState = {
119
151
  instance,
120
- ownsStartPoint: Object.hasOwn(instance, "getStartPoint"),
121
- ownsOffset: Object.hasOwn(instance, "getOffset"),
152
+ hasOwnStartPoint: Object.hasOwn(instance, "getStartPoint"),
153
+ hasOwnOffset: Object.hasOwn(instance, "getOffset"),
122
154
  previousStartPoint: instance.getStartPoint,
123
155
  previousOffset: instance.getOffset,
124
156
  };
@@ -177,6 +209,14 @@ const resolveDragUpdates = (dx: number, dy: number, options: DragOptions): DragO
177
209
  return updates;
178
210
  };
179
211
 
212
+ /**
213
+ * Runs a `drag-begin`, `drag-update`, `drag-end` sequence ending at the offset `dx`, `dy` on the
214
+ * widget's drag gestures, overriding each gesture's start point and offset for the duration so
215
+ * handlers read the simulated values back.
216
+ *
217
+ * @throws When the widget is a Gtk.Range, whose slider reads pointer coordinates from the display,
218
+ * or when it has no Gtk.GestureDrag.
219
+ */
180
220
  const drag = async (widget: Gtk.Widget, dx: number, dy: number, options: DragOptions = {}): Promise<void> => {
181
221
  if (widget instanceof Gtk.Range) {
182
222
  throw new TypeError(
@@ -202,11 +242,22 @@ const emitDrop = (target: Gtk.Widget, content: DropContent, options: DropOptions
202
242
  }
203
243
  };
204
244
 
245
+ /**
246
+ * Emits `drop` with the given content on every drop target attached to the widget.
247
+ *
248
+ * @throws When the widget has no Gtk.DropTarget.
249
+ */
205
250
  const drop = (widget: Gtk.Widget, content: DropContent, options: DropOptions = {}): Promise<void> =>
206
251
  wrapEvent(widget, () => {
207
252
  emitDrop(widget, content, options);
208
253
  });
209
254
 
255
+ /**
256
+ * Emits `drop` with the given content on the target's drop targets, after checking that the source
257
+ * carries a drag source.
258
+ *
259
+ * @throws When the source has no Gtk.DragSource, or the target no Gtk.DropTarget.
260
+ */
210
261
  const dragAndDrop = async (
211
262
  source: Gtk.Widget,
212
263
  target: Gtk.Widget,
@@ -13,29 +13,56 @@ import { clear, copy, cut, paste, type } from "./text.js";
13
13
  * keyboard, pointer, gestures, selection, and scrolling.
14
14
  */
15
15
  type UserEvent = {
16
+ /**
17
+ * Clicks a button, toggles a switch, and otherwise activates the widget, falling back to a click
18
+ * gesture on its nearest clickable ancestor when activation does nothing.
19
+ */
16
20
  click: typeof click;
21
+ /** Emits a two-press click gesture on the widget. */
17
22
  dblClick: typeof dblClick;
23
+ /** Emits a three-press click gesture on the widget. */
18
24
  tripleClick: typeof tripleClick;
25
+ /** Moves focus within the widget's root, forward by default and backward with `isShiftHeld`. */
19
26
  tab: typeof tab;
27
+ /** Focuses an editable widget, applies any initial selection, and inserts the text at the cursor. */
20
28
  type: typeof type;
29
+ /** Empties an editable widget's text. */
21
30
  clear: typeof clear;
31
+ /** Writes an editable widget's current selection to the clipboard. */
22
32
  copy: typeof copy;
33
+ /** Writes an editable widget's current selection to the clipboard and deletes it. */
23
34
  cut: typeof cut;
35
+ /** Inserts the given text, or the clipboard's text, at an editable widget's cursor. */
24
36
  paste: typeof paste;
37
+ /** Selects the items at the given positions in a list view, drop-down, combo box, or list box. */
25
38
  selectOptions: typeof selectOptions;
39
+ /** Deselects the items at the given positions in a list view or list box. */
26
40
  deselectOptions: typeof deselectOptions;
41
+ /** Emits a motion `enter` on the widget, adding a motion controller when it has none. */
27
42
  hover: typeof hover;
43
+ /** Emits a motion `leave` on the widget, adding a motion controller when it has none. */
28
44
  unhover: typeof unhover;
45
+ /** Emits `angle-changed` on the widget's rotate gestures. */
29
46
  rotate: typeof rotate;
47
+ /** Emits `scale-changed` on the widget's zoom gestures. */
30
48
  zoom: typeof zoom;
49
+ /** Emits `swipe` with the given velocity on the widget's swipe gestures. */
31
50
  swipe: typeof swipe;
51
+ /** Emits `pressed` at the given point on the widget's long-press gestures. */
32
52
  longPress: typeof longPress;
53
+ /** Runs a begin, update, and end sequence on the widget's drag gestures, ending at the given offset. */
33
54
  drag: typeof drag;
55
+ /** Emits `drop` with the given content on the widget's drop targets. */
34
56
  drop: typeof drop;
57
+ /** Requires a drag source on the source widget, then emits `drop` with the content on the target's drop targets. */
35
58
  dragAndDrop: typeof dragAndDrop;
59
+ /** Emits a jump `change-value` on a Gtk.Range so it moves to the given value. */
36
60
  slide: typeof slide;
61
+ /** Adds the delta to the adjustments of the widget itself, or of its nearest scrollable ancestor. */
37
62
  scroll: typeof scroll;
63
+ /** Sends a key sequence, dispatching matching shortcuts and tracking held modifiers across calls. */
38
64
  keyboard: (widget: Gtk.Widget, input: string) => Promise<void>;
65
+ /** Applies a pointer token, tracking whether the left button is held across calls. */
39
66
  pointer: (widget: Gtk.Widget, input: PointerInput) => Promise<void>;
40
67
  };
41
68
 
@@ -6,12 +6,13 @@ import { fireEvent } from "../fire-event.js";
6
6
  import { getOrCreateControllers } from "./controller.js";
7
7
  import { wrapEvent } from "./event-wrapper.js";
8
8
 
9
- /** Options for {@link tab}: when `shift` is set, move focus backward instead of forward. */
9
+ /** Options for `userEvent.tab`. */
10
10
  type TabOptions = {
11
- shift?: boolean;
11
+ /** Move focus backward instead of forward. */
12
+ isShiftHeld?: boolean;
12
13
  };
13
14
 
14
- type KeyAction = { keyval: number; press: boolean };
15
+ type KeyAction = { keyval: number; isPress: boolean };
15
16
  type ParseStep = { actions: KeyAction[]; next: number };
16
17
 
17
18
  const KEY_MAP: Record<string, number> = {
@@ -58,9 +59,10 @@ const MODIFIER_KEYVAL_TO_MASK: Record<number, number> = {
58
59
  [Gdk.KEY_Meta_R]: Gdk.ModifierType.META_MASK,
59
60
  };
60
61
 
62
+ /** Moves focus within the widget's root, forward by default and backward when `isShiftHeld` is set. */
61
63
  const tab = (widget: Gtk.Widget, options?: TabOptions): Promise<void> =>
62
64
  wrapEvent(widget, () => {
63
- const direction = options?.shift ? Gtk.DirectionType.TAB_BACKWARD : Gtk.DirectionType.TAB_FORWARD;
65
+ const direction = options?.isShiftHeld ? Gtk.DirectionType.TAB_BACKWARD : Gtk.DirectionType.TAB_FORWARD;
64
66
  const root = widget.getRoot();
65
67
 
66
68
  if (root) {
@@ -68,7 +70,7 @@ const tab = (widget: Gtk.Widget, options?: TabOptions): Promise<void> =>
68
70
  }
69
71
  });
70
72
 
71
- const parseKeyToken = (token: string): { keyval: number; press: boolean; release: boolean } => {
73
+ const parseKeyToken = (token: string): { keyval: number; isPress: boolean; isRelease: boolean } => {
72
74
  let keyName = token;
73
75
  let isPress = true;
74
76
  let isRelease = true;
@@ -87,7 +89,7 @@ const parseKeyToken = (token: string): { keyval: number; press: boolean; release
87
89
  throw new Error(`Unknown key: {${keyName}}`);
88
90
  }
89
91
 
90
- return { keyval, press: isPress, release: isRelease };
92
+ return { keyval, isPress, isRelease };
91
93
  };
92
94
 
93
95
  const parseCharAt = (input: string, i: number): ParseStep => {
@@ -95,8 +97,8 @@ const parseCharAt = (input: string, i: number): ParseStep => {
95
97
 
96
98
  return {
97
99
  actions: [
98
- { keyval, press: true },
99
- { keyval, press: false },
100
+ { keyval, isPress: true },
101
+ { keyval, isPress: false },
100
102
  ],
101
103
  next: i + 1,
102
104
  };
@@ -109,15 +111,15 @@ const parseBraceAt = (input: string, i: number): ParseStep | null => {
109
111
  return null;
110
112
  }
111
113
 
112
- const { keyval, press, release } = parseKeyToken(input.slice(i + 1, endBrace));
114
+ const { keyval, isPress, isRelease } = parseKeyToken(input.slice(i + 1, endBrace));
113
115
  const actions: KeyAction[] = [];
114
116
 
115
- if (press) {
116
- actions.push({ keyval, press: true });
117
+ if (isPress) {
118
+ actions.push({ keyval, isPress: true });
117
119
  }
118
120
 
119
- if (release) {
120
- actions.push({ keyval, press: false });
121
+ if (isRelease) {
122
+ actions.push({ keyval, isPress: false });
121
123
  }
122
124
 
123
125
  return { actions, next: endBrace + 1 };
@@ -151,7 +153,7 @@ const updateModifierState = (state: UserEventState, action: KeyAction): void =>
151
153
  return;
152
154
  }
153
155
 
154
- if (action.press) {
156
+ if (action.isPress) {
155
157
  state.modifierState |= mask;
156
158
  } else {
157
159
  state.modifierState &= ~mask;
@@ -267,13 +269,13 @@ const applyKeyAction = async (
267
269
  action: KeyAction,
268
270
  ): Promise<void> => {
269
271
  updateModifierState(state, action);
270
- const signalName = action.press ? "key-pressed" : "key-released";
272
+ const signalName = action.isPress ? "key-pressed" : "key-released";
271
273
 
272
274
  for (const controller of controllers) {
273
275
  controller.emit(signalName, action.keyval, 0, state.modifierState);
274
276
  }
275
277
 
276
- if (action.press) {
278
+ if (action.isPress) {
277
279
  await handleKeyPress(widget, action.keyval, state.modifierState);
278
280
  }
279
281
  };
@@ -20,21 +20,21 @@ const applyPointerInput = (widget: Gtk.Widget, state: UserEventState, input: Poi
20
20
  if (CLICK_INPUTS.has(input)) {
21
21
  emitPress(widget, controllers, 1);
22
22
  emitRelease(widget, controllers, 1);
23
- state.mouseLeftDown = false;
23
+ state.isMouseLeftDown = false;
24
24
 
25
25
  return;
26
26
  }
27
27
 
28
- if (PRESS_INPUTS.has(input) && !state.mouseLeftDown) {
28
+ if (PRESS_INPUTS.has(input) && !state.isMouseLeftDown) {
29
29
  emitPress(widget, controllers, 1);
30
- state.mouseLeftDown = true;
30
+ state.isMouseLeftDown = true;
31
31
 
32
32
  return;
33
33
  }
34
34
 
35
- if (RELEASE_INPUTS.has(input) && state.mouseLeftDown) {
35
+ if (RELEASE_INPUTS.has(input) && state.isMouseLeftDown) {
36
36
  emitRelease(widget, controllers, 1);
37
- state.mouseLeftDown = false;
37
+ state.isMouseLeftDown = false;
38
38
  }
39
39
  };
40
40
 
@@ -134,6 +134,14 @@ const runSelectionEvent = (
134
134
  byRole(widget, valueArray);
135
135
  });
136
136
 
137
+ /**
138
+ * Selects the items at the given positions through a list, grid, or column view's selection model,
139
+ * by setting the active item of a drop-down or combo box, or by selecting list box rows. An empty
140
+ * array clears a view's selection.
141
+ *
142
+ * @throws When a view has no selection model, when a combo box is given more than one position, or
143
+ * when the widget is neither a view nor something with the combo box or list role.
144
+ */
137
145
  const selectOptions = (widget: Gtk.Widget, values: number | number[]): Promise<void> =>
138
146
  runSelectionEvent(widget, values, selectInListView, selectByRole);
139
147
 
@@ -153,6 +161,13 @@ const deselectByRole = (widget: Gtk.Widget, valueArray: number[]): void => {
153
161
  applyListBoxRows(widget, valueArray, unselectListBoxRow);
154
162
  };
155
163
 
164
+ /**
165
+ * Unselects the items at the given positions in a list, grid, or column view, or the rows at those
166
+ * indices in a Gtk.ListBox.
167
+ *
168
+ * @throws When a view has no selection model, or when the widget is neither one of those views nor
169
+ * a Gtk.ListBox.
170
+ */
156
171
  const deselectOptions = (widget: Gtk.Widget, values: number | number[]): Promise<void> =>
157
172
  runSelectionEvent(widget, values, deselectInListView, deselectByRole);
158
173
 
@@ -1,8 +1,8 @@
1
1
  type UserEventState = {
2
2
  modifierState: number;
3
- mouseLeftDown: boolean;
3
+ isMouseLeftDown: boolean;
4
4
  };
5
5
 
6
- const createInitialState = (): UserEventState => ({ modifierState: 0, mouseLeftDown: false });
6
+ const createInitialState = (): UserEventState => ({ modifierState: 0, isMouseLeftDown: false });
7
7
 
8
8
  export { createInitialState, type UserEventState };
@@ -5,10 +5,10 @@ import { EDITABLE_ROLES, type EditableTarget, getEditableDelegate, isEditable }
5
5
  import { formatRoleList } from "../role-helpers.js";
6
6
  import { wrapEvent } from "./event-wrapper.js";
7
7
 
8
- /** Options for {@link type}. */
8
+ /** Options for `userEvent.type`. */
9
9
  type TypeOptions = {
10
- /** Do not focus the widget before typing. */
11
- skipClick?: boolean | undefined;
10
+ /** Focus the widget before typing; defaults to true. */
11
+ shouldFocus?: boolean | undefined;
12
12
  /** Select from this offset before typing, replacing the selected range with the typed text. */
13
13
  initialSelectionStart?: number | undefined;
14
14
  /** End offset of the initial selection (defaults to the start offset). */
@@ -131,9 +131,15 @@ const runEditableEvent = (
131
131
  action(widget);
132
132
  });
133
133
 
134
+ /**
135
+ * Focuses the widget unless `shouldFocus` is false, applies any initial selection, and inserts the text
136
+ * at the cursor.
137
+ *
138
+ * @throws When the widget is neither a Gtk.Editable nor a Gtk.TextView.
139
+ */
134
140
  const type = (widget: Gtk.Widget, text: string, options?: TypeOptions): Promise<void> =>
135
141
  runEditableEvent(widget, "Cannot type into element", (editable) => {
136
- if (!options?.skipClick) {
142
+ if (options?.shouldFocus ?? true) {
137
143
  editable.grabFocus();
138
144
  }
139
145
 
@@ -141,22 +147,43 @@ const type = (widget: Gtk.Widget, text: string, options?: TypeOptions): Promise<
141
147
  insertEditableText(editable, text);
142
148
  });
143
149
 
150
+ /**
151
+ * Replaces an editable widget's text with the empty string.
152
+ *
153
+ * @throws When the widget is neither a Gtk.Editable nor a Gtk.TextView.
154
+ */
144
155
  const clear = (widget: Gtk.Widget): Promise<void> =>
145
156
  runEditableEvent(widget, "Cannot clear element", (editable) => {
146
157
  setEditableText(editable, "");
147
158
  });
148
159
 
160
+ /**
161
+ * Writes an editable widget's selected text to its clipboard, or the empty string when nothing is selected.
162
+ *
163
+ * @throws When the widget is neither a Gtk.Editable nor a Gtk.TextView.
164
+ */
149
165
  const copy = (widget: Gtk.Widget): Promise<void> =>
150
166
  runEditableEvent(widget, "Cannot copy", (editable) => {
151
167
  writeClipboardText(editable, readSelection(editable));
152
168
  });
153
169
 
170
+ /**
171
+ * Writes an editable widget's selected text to its clipboard, then deletes that selection.
172
+ *
173
+ * @throws When the widget is neither a Gtk.Editable nor a Gtk.TextView.
174
+ */
154
175
  const cut = (widget: Gtk.Widget): Promise<void> =>
155
176
  runEditableEvent(widget, "Cannot cut", (editable) => {
156
177
  writeClipboardText(editable, readSelection(editable));
157
178
  deleteSelection(editable);
158
179
  });
159
180
 
181
+ /**
182
+ * Inserts the given text at an editable widget's cursor, reading the clipboard instead when no text
183
+ * is given.
184
+ *
185
+ * @throws When the widget is neither a Gtk.Editable nor a Gtk.TextView.
186
+ */
160
187
  const paste = async (widget: Gtk.Widget, text?: string): Promise<void> => {
161
188
  if (!isEditable(widget)) {
162
189
  throw new Error(`Cannot paste: ${EDITABLE_REQUIRED}`);
package/src/wait-for.ts CHANGED
@@ -5,7 +5,9 @@ import { getConfig } from "./config.js";
5
5
  import { timeoutError } from "./errors.js";
6
6
 
7
7
  type PollResult<T> = { status: "resolved"; value: T } | { status: "timedout"; lastError: Error | null };
8
+ /** Widgets watched for removal; null counts as already removed. */
8
9
  type RemovalTarget = Gtk.Widget | Gtk.Widget[] | null;
10
+ /** The widgets to watch for removal, or a function re-read on every poll to locate them. */
9
11
  type ElementOrCallback = Gtk.Widget | Gtk.Widget[] | (() => RemovalTarget);
10
12
 
11
13
  const DEFAULT_INTERVAL = 50;
@@ -11,7 +11,6 @@ type WidgetValue = {
11
11
  };
12
12
 
13
13
  type ValueTriplet = { now: number | null; min: number | null; max: number | null };
14
- /** A widget's checked state: on, off, or the mixed state of an inconsistent check button. */
15
14
  type CheckedState = "checked" | "unchecked" | "mixed";
16
15
 
17
16
  const DEFAULT_TEXT_GETTERS = ["getLabel", "getText", "getTitle"] as const;
@@ -158,6 +157,12 @@ const textContentParts = (widget: Gtk.Widget): string[] => {
158
157
  return [...getChildren(widget)].flatMap((child) => textContentParts(child));
159
158
  };
160
159
 
160
+ /**
161
+ * Returns a widget's own text, or the space-joined text of its descendants when it has none of its
162
+ * own, or null when neither produces a value.
163
+ *
164
+ * @param widget The widget whose subtree is read.
165
+ */
161
166
  const getWidgetTextContent = (widget: Gtk.Widget): string | null => {
162
167
  const parts = textContentParts(widget);
163
168
 
@@ -370,12 +375,23 @@ const getWidgetLevel = (widget: Gtk.Widget): number | null => {
370
375
  return readAccessibleNumber(widget, "accessibleLevel");
371
376
  };
372
377
 
378
+ /**
379
+ * Returns the accessible invalid state declared on a widget, or null when it declares none.
380
+ *
381
+ * @param widget The widget to read the state from.
382
+ */
373
383
  const getWidgetInvalidState = (widget: Gtk.Widget): Gtk.AccessibleInvalidState | null => {
374
384
  const value = readAccessibleNumber(widget, "accessibleInvalid");
375
385
 
376
386
  return value ?? null;
377
387
  };
378
388
 
389
+ /**
390
+ * Returns the widgets a widget's accessible error-message relation points at, or null when it
391
+ * declares none.
392
+ *
393
+ * @param widget The widget to read the relation from.
394
+ */
379
395
  const getWidgetErrorMessage = (widget: Gtk.Widget): Gtk.Widget[] | null =>
380
396
  readAccessibleWidgets(widget, "accessibleErrorMessage");
381
397