@gtkx/testing 0.6.1 → 0.7.0

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.
package/dist/queries.d.ts CHANGED
@@ -1,5 +1,4 @@
1
- import type * as Gtk from "@gtkx/ffi/gtk";
2
- import { AccessibleRole } from "@gtkx/ffi/gtk";
1
+ import * as Gtk from "@gtkx/ffi/gtk";
3
2
  import type { ByRoleOptions, TextMatch, TextMatchOptions } from "./types.js";
4
3
  type Container = Gtk.Application | Gtk.Widget;
5
4
  /**
@@ -9,7 +8,7 @@ type Container = Gtk.Application | Gtk.Widget;
9
8
  * @param options - Additional filtering options (name, checked, expanded)
10
9
  * @returns Promise resolving to the matching widget
11
10
  */
12
- export declare const findByRole: (container: Container, role: AccessibleRole, options?: ByRoleOptions) => Promise<Gtk.Widget>;
11
+ export declare const findByRole: (container: Container, role: Gtk.AccessibleRole, options?: ByRoleOptions) => Promise<Gtk.Widget>;
13
12
  /**
14
13
  * Waits for and finds all widgets matching the specified accessible role.
15
14
  * @param container - The container to search within
@@ -17,7 +16,7 @@ export declare const findByRole: (container: Container, role: AccessibleRole, op
17
16
  * @param options - Additional filtering options (name, checked, expanded)
18
17
  * @returns Promise resolving to array of matching widgets
19
18
  */
20
- export declare const findAllByRole: (container: Container, role: AccessibleRole, options?: ByRoleOptions) => Promise<Gtk.Widget[]>;
19
+ export declare const findAllByRole: (container: Container, role: Gtk.AccessibleRole, options?: ByRoleOptions) => Promise<Gtk.Widget[]>;
21
20
  /**
22
21
  * Waits for and finds a single widget matching the specified label text.
23
22
  * @param container - The container to search within
package/dist/queries.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { getInterface } from "@gtkx/ffi";
2
- import { Accessible, AccessibleRole, Button, CheckButton, Editable, Expander, Frame, Label, MenuButton, StackPage, Switch, ToggleButton, Window, } from "@gtkx/ffi/gtk";
2
+ import * as Gtk from "@gtkx/ffi/gtk";
3
3
  import { findAll } from "./traversal.js";
4
4
  import { waitFor } from "./wait-for.js";
5
5
  const buildNormalizer = (options) => {
@@ -39,35 +39,40 @@ const matchText = (actual, expected, widget, options) => {
39
39
  return exact ? normalizedActual === normalizedExpected : normalizedActual.includes(normalizedExpected);
40
40
  };
41
41
  const ROLES_WITH_INTERNAL_LABELS = new Set([
42
- AccessibleRole.BUTTON,
43
- AccessibleRole.TOGGLE_BUTTON,
44
- AccessibleRole.CHECKBOX,
45
- AccessibleRole.RADIO,
46
- AccessibleRole.MENU_ITEM,
47
- AccessibleRole.MENU_ITEM_CHECKBOX,
48
- AccessibleRole.MENU_ITEM_RADIO,
49
- AccessibleRole.TAB,
50
- AccessibleRole.LINK,
42
+ Gtk.AccessibleRole.BUTTON,
43
+ Gtk.AccessibleRole.TOGGLE_BUTTON,
44
+ Gtk.AccessibleRole.CHECKBOX,
45
+ Gtk.AccessibleRole.RADIO,
46
+ Gtk.AccessibleRole.MENU_ITEM,
47
+ Gtk.AccessibleRole.MENU_ITEM_CHECKBOX,
48
+ Gtk.AccessibleRole.MENU_ITEM_RADIO,
49
+ Gtk.AccessibleRole.TAB,
50
+ Gtk.AccessibleRole.LINK,
51
51
  ]);
52
52
  const isInternalLabel = (widget) => {
53
- const accessible = getInterface(widget, Accessible);
54
- if (!accessible || accessible.getAccessibleRole() !== AccessibleRole.LABEL)
53
+ const accessible = getInterface(widget.id, Gtk.Accessible);
54
+ if (!accessible || accessible.getAccessibleRole() !== Gtk.AccessibleRole.LABEL)
55
55
  return false;
56
56
  const parent = widget.getParent();
57
57
  if (!parent)
58
58
  return false;
59
- const parentAccessible = getInterface(parent, Accessible);
59
+ const parentAccessible = getInterface(parent.id, Gtk.Accessible);
60
60
  if (!parentAccessible)
61
61
  return false;
62
62
  return ROLES_WITH_INTERNAL_LABELS.has(parentAccessible.getAccessibleRole());
63
63
  };
64
+ const getLabelText = (widget) => {
65
+ const asLabel = widget;
66
+ const asInscription = widget;
67
+ return asLabel.getLabel?.() ?? asInscription.getText?.() ?? null;
68
+ };
64
69
  const collectChildLabels = (widget) => {
65
70
  const labels = [];
66
71
  let child = widget.getFirstChild();
67
72
  while (child) {
68
- const childAccessible = getInterface(child, Accessible);
69
- if (childAccessible?.getAccessibleRole() === AccessibleRole.LABEL) {
70
- const labelText = getInterface(child, Label)?.getLabel();
73
+ const childAccessible = getInterface(child.id, Gtk.Accessible);
74
+ if (childAccessible?.getAccessibleRole() === Gtk.AccessibleRole.LABEL) {
75
+ const labelText = getLabelText(child);
71
76
  if (labelText)
72
77
  labels.push(labelText);
73
78
  }
@@ -79,40 +84,49 @@ const collectChildLabels = (widget) => {
79
84
  const getWidgetText = (widget) => {
80
85
  if (isInternalLabel(widget))
81
86
  return null;
82
- const role = getInterface(widget, Accessible)?.getAccessibleRole();
87
+ const role = getInterface(widget.id, Gtk.Accessible)?.getAccessibleRole();
83
88
  if (role === undefined)
84
89
  return null;
85
90
  switch (role) {
86
- case AccessibleRole.BUTTON:
87
- case AccessibleRole.LINK:
88
- case AccessibleRole.TAB: {
89
- const directLabel = getInterface(widget, Button)?.getLabel() ??
90
- getInterface(widget, MenuButton)?.getLabel() ??
91
- getInterface(widget, Expander)?.getLabel();
91
+ case Gtk.AccessibleRole.BUTTON:
92
+ case Gtk.AccessibleRole.LINK:
93
+ case Gtk.AccessibleRole.TAB: {
94
+ const directLabel = widget.getLabel?.() ??
95
+ widget.getLabel?.() ??
96
+ widget.getLabel?.();
92
97
  if (directLabel)
93
98
  return directLabel;
94
99
  const childLabels = collectChildLabels(widget);
95
100
  return childLabels.length > 0 ? childLabels.join(" ") : null;
96
101
  }
97
- case AccessibleRole.TOGGLE_BUTTON:
98
- return getInterface(widget, ToggleButton)?.getLabel() ?? null;
99
- case AccessibleRole.CHECKBOX:
100
- case AccessibleRole.RADIO:
101
- return getInterface(widget, CheckButton)?.getLabel() ?? null;
102
- case AccessibleRole.LABEL:
103
- return getInterface(widget, Label)?.getLabel() ?? null;
104
- case AccessibleRole.TEXT_BOX:
105
- case AccessibleRole.SEARCH_BOX:
106
- case AccessibleRole.SPIN_BUTTON:
107
- return getInterface(widget, Editable)?.getText() ?? null;
108
- case AccessibleRole.GROUP:
109
- return getInterface(widget, Frame)?.getLabel() ?? null;
110
- case AccessibleRole.WINDOW:
111
- case AccessibleRole.DIALOG:
112
- case AccessibleRole.ALERT_DIALOG:
113
- return getInterface(widget, Window)?.getTitle() ?? null;
114
- case AccessibleRole.TAB_PANEL:
115
- return getInterface(widget, StackPage)?.getTitle() ?? null;
102
+ case Gtk.AccessibleRole.TOGGLE_BUTTON:
103
+ return widget.getLabel?.() ?? null;
104
+ case Gtk.AccessibleRole.CHECKBOX:
105
+ case Gtk.AccessibleRole.RADIO:
106
+ return widget.getLabel?.() ?? null;
107
+ case Gtk.AccessibleRole.LABEL:
108
+ return getLabelText(widget);
109
+ case Gtk.AccessibleRole.TEXT_BOX:
110
+ case Gtk.AccessibleRole.SEARCH_BOX:
111
+ case Gtk.AccessibleRole.SPIN_BUTTON:
112
+ return getInterface(widget.id, Gtk.Editable)?.getText() ?? null;
113
+ case Gtk.AccessibleRole.GROUP:
114
+ return widget.getLabel?.() ?? null;
115
+ case Gtk.AccessibleRole.WINDOW:
116
+ case Gtk.AccessibleRole.DIALOG:
117
+ case Gtk.AccessibleRole.ALERT_DIALOG:
118
+ return widget.getTitle() ?? null;
119
+ case Gtk.AccessibleRole.TAB_PANEL: {
120
+ const parent = widget.getParent();
121
+ if (parent) {
122
+ const stack = parent;
123
+ const page = stack.getPage?.(widget);
124
+ if (page) {
125
+ return page.getTitle() ?? null;
126
+ }
127
+ }
128
+ return null;
129
+ }
116
130
  default:
117
131
  return null;
118
132
  }
@@ -121,32 +135,32 @@ const getWidgetTestId = (widget) => {
121
135
  return widget.getName();
122
136
  };
123
137
  const getWidgetCheckedState = (widget) => {
124
- const accessible = getInterface(widget, Accessible);
138
+ const accessible = getInterface(widget.id, Gtk.Accessible);
125
139
  if (!accessible)
126
140
  return undefined;
127
141
  const role = accessible.getAccessibleRole();
128
142
  switch (role) {
129
- case AccessibleRole.CHECKBOX:
130
- case AccessibleRole.RADIO:
131
- return getInterface(widget, CheckButton)?.getActive();
132
- case AccessibleRole.TOGGLE_BUTTON:
133
- return getInterface(widget, ToggleButton)?.getActive();
134
- case AccessibleRole.SWITCH:
135
- return getInterface(widget, Switch)?.getActive();
143
+ case Gtk.AccessibleRole.CHECKBOX:
144
+ case Gtk.AccessibleRole.RADIO:
145
+ return widget.getActive();
146
+ case Gtk.AccessibleRole.TOGGLE_BUTTON:
147
+ return widget.getActive();
148
+ case Gtk.AccessibleRole.SWITCH:
149
+ return widget.getActive();
136
150
  default:
137
151
  return undefined;
138
152
  }
139
153
  };
140
154
  const getWidgetExpandedState = (widget) => {
141
- const accessible = getInterface(widget, Accessible);
155
+ const accessible = getInterface(widget.id, Gtk.Accessible);
142
156
  if (!accessible)
143
157
  return undefined;
144
158
  const role = accessible.getAccessibleRole();
145
- if (role === AccessibleRole.BUTTON) {
159
+ if (role === Gtk.AccessibleRole.BUTTON) {
146
160
  const parent = widget.getParent();
147
161
  if (!parent)
148
162
  return undefined;
149
- return getInterface(parent, Expander)?.getExpanded();
163
+ return parent.getExpanded?.();
150
164
  }
151
165
  return undefined;
152
166
  };
@@ -170,7 +184,7 @@ const matchByRoleOptions = (widget, options) => {
170
184
  }
171
185
  return true;
172
186
  };
173
- const formatRole = (role) => AccessibleRole[role] ?? String(role);
187
+ const formatRole = (role) => Gtk.AccessibleRole[role] ?? String(role);
174
188
  const formatByRoleError = (role, options) => {
175
189
  const parts = [`role "${formatRole(role)}"`];
176
190
  if (options?.name)
@@ -189,7 +203,7 @@ const formatByRoleError = (role, options) => {
189
203
  };
190
204
  const getAllByRole = (container, role, options) => {
191
205
  const matches = findAll(container, (node) => {
192
- const accessible = getInterface(node, Accessible);
206
+ const accessible = getInterface(node.id, Gtk.Accessible);
193
207
  if (!accessible || accessible.getAccessibleRole() !== role)
194
208
  return false;
195
209
  return matchByRoleOptions(node, options);
package/dist/render.js CHANGED
@@ -11,18 +11,18 @@ let container = null;
11
11
  const getWidgetLabel = (widget) => {
12
12
  if (!hasLabel(widget))
13
13
  return null;
14
- const accessible = getInterface(widget, Gtk.Accessible);
14
+ const accessible = getInterface(widget.id, Gtk.Accessible);
15
15
  if (!accessible)
16
16
  return null;
17
17
  const role = accessible.getAccessibleRole();
18
18
  if (role === Gtk.AccessibleRole.LABEL) {
19
- return getInterface(widget, Gtk.Label)?.getLabel() ?? null;
19
+ return widget.getLabel?.() ?? null;
20
20
  }
21
- return getInterface(widget, Gtk.Button)?.getLabel() ?? null;
21
+ return widget.getLabel?.() ?? null;
22
22
  };
23
23
  const printWidgetTree = (root, indent = 0) => {
24
24
  const prefix = " ".repeat(indent);
25
- const accessibleRole = getInterface(root, Gtk.Accessible)?.getAccessibleRole();
25
+ const accessibleRole = getInterface(root.id, Gtk.Accessible)?.getAccessibleRole();
26
26
  const role = accessibleRole !== undefined ? (Gtk.AccessibleRole[accessibleRole] ?? "UNKNOWN") : "UNKNOWN";
27
27
  const labelText = getWidgetLabel(root);
28
28
  const label = labelText ? ` label="${labelText}"` : "";
@@ -1,5 +1,5 @@
1
- import { getInterface } from "@gtkx/ffi";
2
- import { Accessible, AccessibleRole, DirectionType, Editable, Widget, } from "@gtkx/ffi/gtk";
1
+ import { getInterface, getObject } from "@gtkx/ffi";
2
+ import { Accessible, AccessibleRole, DirectionType, Editable, } from "@gtkx/ffi/gtk";
3
3
  import { fireEvent } from "./fire-event.js";
4
4
  import { tick } from "./timing.js";
5
5
  import { isEditable } from "./widget.js";
@@ -10,14 +10,14 @@ const TOGGLEABLE_ROLES = new Set([
10
10
  AccessibleRole.SWITCH,
11
11
  ]);
12
12
  const isToggleable = (widget) => {
13
- const accessible = getInterface(widget, Accessible);
13
+ const accessible = getInterface(widget.id, Accessible);
14
14
  if (!accessible)
15
15
  return false;
16
16
  return TOGGLEABLE_ROLES.has(accessible.getAccessibleRole());
17
17
  };
18
18
  const click = async (element) => {
19
19
  if (isToggleable(element)) {
20
- const role = getInterface(element, Accessible)?.getAccessibleRole();
20
+ const role = getInterface(element.id, Accessible)?.getAccessibleRole();
21
21
  if (role === AccessibleRole.CHECKBOX || role === AccessibleRole.RADIO) {
22
22
  const checkButton = element;
23
23
  checkButton.setActive(!checkButton.getActive());
@@ -53,7 +53,7 @@ const tab = async (element, options) => {
53
53
  const direction = options?.shift ? DirectionType.TAB_BACKWARD : DirectionType.TAB_FORWARD;
54
54
  const root = element.getRoot();
55
55
  if (root) {
56
- getInterface(root, Widget)?.childFocus(direction);
56
+ getObject(root.id).childFocus(direction);
57
57
  }
58
58
  await tick();
59
59
  };
@@ -61,7 +61,7 @@ const type = async (element, text) => {
61
61
  if (!isEditable(element)) {
62
62
  throw new Error("Cannot type into element: element is not editable (TEXT_BOX, SEARCH_BOX, or SPIN_BUTTON)");
63
63
  }
64
- const editable = getInterface(element, Editable);
64
+ const editable = getInterface(element.id, Editable);
65
65
  if (!editable)
66
66
  return;
67
67
  const currentText = editable.getText();
@@ -72,12 +72,12 @@ const clear = async (element) => {
72
72
  if (!isEditable(element)) {
73
73
  throw new Error("Cannot clear element: element is not editable (TEXT_BOX, SEARCH_BOX, or SPIN_BUTTON)");
74
74
  }
75
- getInterface(element, Editable)?.setText("");
75
+ getInterface(element.id, Editable)?.setText("");
76
76
  await tick();
77
77
  };
78
78
  const SELECTABLE_ROLES = new Set([AccessibleRole.COMBO_BOX, AccessibleRole.LIST]);
79
79
  const isSelectable = (widget) => {
80
- const accessible = getInterface(widget, Accessible);
80
+ const accessible = getInterface(widget.id, Accessible);
81
81
  if (!accessible)
82
82
  return false;
83
83
  return SELECTABLE_ROLES.has(accessible.getAccessibleRole());
@@ -86,7 +86,7 @@ const selectOptions = async (element, values) => {
86
86
  if (!isSelectable(element)) {
87
87
  throw new Error("Cannot select options: element is not a selectable widget (COMBO_BOX or LIST)");
88
88
  }
89
- const role = getInterface(element, Accessible)?.getAccessibleRole();
89
+ const role = getInterface(element.id, Accessible)?.getAccessibleRole();
90
90
  const valueArray = Array.isArray(values) ? values : [values];
91
91
  if (role === AccessibleRole.COMBO_BOX) {
92
92
  if (valueArray.length > 1) {
@@ -120,7 +120,7 @@ const selectOptions = async (element, values) => {
120
120
  await tick();
121
121
  };
122
122
  const deselectOptions = async (element, values) => {
123
- const role = getInterface(element, Accessible)?.getAccessibleRole();
123
+ const role = getInterface(element.id, Accessible)?.getAccessibleRole();
124
124
  if (role !== AccessibleRole.LIST) {
125
125
  throw new Error("Cannot deselect options: only ListBox supports deselection");
126
126
  }
package/dist/widget.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type * as Gtk from "@gtkx/ffi/gtk";
1
+ import * as Gtk from "@gtkx/ffi/gtk";
2
2
  /**
3
3
  * Checks if a widget has an editable accessible role (text box, search box, or spin button).
4
4
  */
package/dist/widget.js CHANGED
@@ -1,30 +1,34 @@
1
1
  import { getInterface } from "@gtkx/ffi";
2
- import { Accessible, AccessibleRole } from "@gtkx/ffi/gtk";
3
- const EDITABLE_ROLES = new Set([AccessibleRole.TEXT_BOX, AccessibleRole.SEARCH_BOX, AccessibleRole.SPIN_BUTTON]);
2
+ import * as Gtk from "@gtkx/ffi/gtk";
3
+ const EDITABLE_ROLES = new Set([
4
+ Gtk.AccessibleRole.TEXT_BOX,
5
+ Gtk.AccessibleRole.SEARCH_BOX,
6
+ Gtk.AccessibleRole.SPIN_BUTTON,
7
+ ]);
4
8
  /**
5
9
  * Checks if a widget has an editable accessible role (text box, search box, or spin button).
6
10
  */
7
11
  export const isEditable = (widget) => {
8
- const accessible = getInterface(widget, Accessible);
12
+ const accessible = getInterface(widget.id, Gtk.Accessible);
9
13
  if (!accessible)
10
14
  return false;
11
15
  return EDITABLE_ROLES.has(accessible.getAccessibleRole());
12
16
  };
13
17
  const LABEL_ROLES = new Set([
14
- AccessibleRole.BUTTON,
15
- AccessibleRole.TOGGLE_BUTTON,
16
- AccessibleRole.CHECKBOX,
17
- AccessibleRole.RADIO,
18
- AccessibleRole.LABEL,
19
- AccessibleRole.MENU_ITEM,
20
- AccessibleRole.MENU_ITEM_CHECKBOX,
21
- AccessibleRole.MENU_ITEM_RADIO,
18
+ Gtk.AccessibleRole.BUTTON,
19
+ Gtk.AccessibleRole.TOGGLE_BUTTON,
20
+ Gtk.AccessibleRole.CHECKBOX,
21
+ Gtk.AccessibleRole.RADIO,
22
+ Gtk.AccessibleRole.LABEL,
23
+ Gtk.AccessibleRole.MENU_ITEM,
24
+ Gtk.AccessibleRole.MENU_ITEM_CHECKBOX,
25
+ Gtk.AccessibleRole.MENU_ITEM_RADIO,
22
26
  ]);
23
27
  /**
24
28
  * Checks if a widget has an accessible role that supports labels.
25
29
  */
26
30
  export const hasLabel = (widget) => {
27
- const accessible = getInterface(widget, Accessible);
31
+ const accessible = getInterface(widget.id, Gtk.Accessible);
28
32
  if (!accessible)
29
33
  return false;
30
34
  return LABEL_ROLES.has(accessible.getAccessibleRole());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gtkx/testing",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "description": "Testing utilities for GTKX applications",
5
5
  "keywords": [
6
6
  "gtk",
@@ -32,9 +32,9 @@
32
32
  "dist"
33
33
  ],
34
34
  "dependencies": {
35
- "@gtkx/ffi": "0.6.1",
36
- "@gtkx/react": "0.6.1",
37
- "@gtkx/native": "0.6.1"
35
+ "@gtkx/native": "0.7.0",
36
+ "@gtkx/ffi": "0.7.0",
37
+ "@gtkx/react": "0.7.0"
38
38
  },
39
39
  "scripts": {
40
40
  "build": "tsc -b && cp ../../README.md .",