@gtkx/testing 0.2.7 → 0.3.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.
@@ -14,5 +14,5 @@ import { call } from "@gtkx/native";
14
14
  * fireEvent(widget, "custom-signal", { type: { type: "int", size: 32 }, value: 42 })
15
15
  */
16
16
  export const fireEvent = (element, signalName, ...args) => {
17
- call("libgobject-2.0.so.0", "g_signal_emit_by_name", [{ type: { type: "gobject" }, value: element.ptr }, { type: { type: "string" }, value: signalName }, ...args], { type: "undefined" });
17
+ call("libgobject-2.0.so.0", "g_signal_emit_by_name", [{ type: { type: "gobject" }, value: element.id }, { type: { type: "string" }, value: signalName }, ...args], { type: "undefined" });
18
18
  };
package/dist/queries.js CHANGED
@@ -1,8 +1,7 @@
1
- import { getObject } from "@gtkx/ffi";
2
- import { AccessibleRole, Button, CheckButton, Editable, Expander, Frame, Label, StackPage, Switch, ToggleButton, Window, } from "@gtkx/ffi/gtk";
1
+ import { cast } from "@gtkx/ffi";
2
+ import { AccessibleRole, } from "@gtkx/ffi/gtk";
3
3
  import { findAll } from "./traversal.js";
4
4
  import { waitFor } from "./wait-for.js";
5
- import { asAccessible } from "./widget.js";
6
5
  const DEFAULT_NORMALIZER = (text) => text.trim().replace(/\s+/g, " ");
7
6
  const normalizeText = (text, options) => {
8
7
  const normalizer = options?.normalizer ?? DEFAULT_NORMALIZER;
@@ -19,14 +18,6 @@ const matchText = (actual, expected, options) => {
19
18
  }
20
19
  return expected.test(normalizedActual);
21
20
  };
22
- const asButton = (widget) => getObject(widget.ptr, Button);
23
- const asLabel = (widget) => getObject(widget.ptr, Label);
24
- const asCheckButton = (widget) => getObject(widget.ptr, CheckButton);
25
- const asToggleButton = (widget) => getObject(widget.ptr, ToggleButton);
26
- const asExpander = (widget) => getObject(widget.ptr, Expander);
27
- const asFrame = (widget) => getObject(widget.ptr, Frame);
28
- const asWindow = (widget) => getObject(widget.ptr, Window);
29
- const asStackPage = (widget) => getObject(widget.ptr, StackPage);
30
21
  const ROLES_WITH_INTERNAL_LABELS = new Set([
31
22
  AccessibleRole.BUTTON,
32
23
  AccessibleRole.TOGGLE_BUTTON,
@@ -39,38 +30,38 @@ const ROLES_WITH_INTERNAL_LABELS = new Set([
39
30
  AccessibleRole.LINK,
40
31
  ]);
41
32
  const isInternalLabel = (widget) => {
42
- const accessible = asAccessible(widget);
33
+ const accessible = cast(widget);
43
34
  if (accessible.getAccessibleRole() !== AccessibleRole.LABEL)
44
35
  return false;
45
36
  const parent = widget.getParent();
46
37
  if (!parent)
47
38
  return false;
48
- const parentRole = asAccessible(parent).getAccessibleRole();
39
+ const parentRole = cast(parent).getAccessibleRole();
49
40
  return ROLES_WITH_INTERNAL_LABELS.has(parentRole);
50
41
  };
51
42
  const getWidgetText = (widget) => {
52
43
  if (isInternalLabel(widget))
53
44
  return null;
54
- const role = asAccessible(widget).getAccessibleRole();
45
+ const role = cast(widget).getAccessibleRole();
55
46
  switch (role) {
56
47
  case AccessibleRole.BUTTON:
57
48
  case AccessibleRole.LINK:
58
49
  case AccessibleRole.TAB:
59
- return asButton(widget).getLabel();
50
+ return cast(widget).getLabel();
60
51
  case AccessibleRole.TOGGLE_BUTTON:
61
- return asToggleButton(widget).getLabel();
52
+ return cast(widget).getLabel();
62
53
  case AccessibleRole.CHECKBOX:
63
54
  case AccessibleRole.RADIO:
64
- return asCheckButton(widget).getLabel();
55
+ return cast(widget).getLabel();
65
56
  case AccessibleRole.LABEL:
66
- return asLabel(widget).getLabel();
57
+ return cast(widget).getLabel();
67
58
  case AccessibleRole.TEXT_BOX:
68
59
  case AccessibleRole.SEARCH_BOX:
69
60
  case AccessibleRole.SPIN_BUTTON:
70
- return getObject(widget.ptr, Editable).getText();
61
+ return cast(widget).getText();
71
62
  case AccessibleRole.GROUP:
72
63
  try {
73
- return asFrame(widget).getLabel();
64
+ return cast(widget).getLabel();
74
65
  }
75
66
  catch {
76
67
  return null;
@@ -78,10 +69,10 @@ const getWidgetText = (widget) => {
78
69
  case AccessibleRole.WINDOW:
79
70
  case AccessibleRole.DIALOG:
80
71
  case AccessibleRole.ALERT_DIALOG:
81
- return asWindow(widget).getTitle();
72
+ return cast(widget).getTitle();
82
73
  case AccessibleRole.TAB_PANEL:
83
74
  try {
84
- return asStackPage(widget).getTitle();
75
+ return cast(widget).getTitle();
85
76
  }
86
77
  catch {
87
78
  return null;
@@ -95,28 +86,27 @@ const getWidgetText = (widget) => {
95
86
  const getWidgetTestId = (widget) => {
96
87
  return widget.getName();
97
88
  };
98
- const asSwitch = (widget) => getObject(widget.ptr, Switch);
99
89
  const getWidgetCheckedState = (widget) => {
100
- const role = asAccessible(widget).getAccessibleRole();
90
+ const role = cast(widget).getAccessibleRole();
101
91
  switch (role) {
102
92
  case AccessibleRole.CHECKBOX:
103
93
  case AccessibleRole.RADIO:
104
- return asCheckButton(widget).getActive();
94
+ return cast(widget).getActive();
105
95
  case AccessibleRole.TOGGLE_BUTTON:
106
- return asToggleButton(widget).getActive();
96
+ return cast(widget).getActive();
107
97
  case AccessibleRole.SWITCH:
108
- return asSwitch(widget).getActive();
98
+ return cast(widget).getActive();
109
99
  default:
110
100
  return undefined;
111
101
  }
112
102
  };
113
103
  const getWidgetExpandedState = (widget) => {
114
- const role = asAccessible(widget).getAccessibleRole();
104
+ const role = cast(widget).getAccessibleRole();
115
105
  if (role === AccessibleRole.BUTTON) {
116
106
  const parent = widget.getParent();
117
107
  if (!parent)
118
108
  return undefined;
119
- return asExpander(parent).getExpanded();
109
+ return cast(parent).getExpanded();
120
110
  }
121
111
  return undefined;
122
112
  };
@@ -159,7 +149,7 @@ const formatByRoleError = (role, options) => {
159
149
  };
160
150
  const getAllByRole = (container, role, options) => {
161
151
  const matches = findAll(container, (node) => {
162
- if (asAccessible(node).getAccessibleRole() !== role)
152
+ if (cast(node).getAccessibleRole() !== role)
163
153
  return false;
164
154
  return matchByRoleOptions(node, options);
165
155
  });
package/dist/render.js CHANGED
@@ -1,26 +1,26 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { getCurrentApp, getObject, start, stop } from "@gtkx/ffi";
2
+ import { cast, getCurrentApp, start, stop } from "@gtkx/ffi";
3
3
  import * as Gtk from "@gtkx/ffi/gtk";
4
4
  import { ApplicationWindow, reconciler } from "@gtkx/react";
5
5
  import * as queries from "./queries.js";
6
6
  import { setScreenRoot } from "./screen.js";
7
7
  import { tick } from "./timing.js";
8
- import { asAccessible, hasLabel } from "./widget.js";
8
+ import { hasLabel } from "./widget.js";
9
9
  const ROOT_NODE_CONTAINER = Symbol.for("ROOT_NODE_CONTAINER");
10
10
  const APP_ID = "com.gtkx.testing";
11
11
  let container = null;
12
12
  const getWidgetLabel = (widget) => {
13
13
  if (!hasLabel(widget))
14
14
  return null;
15
- const role = asAccessible(widget).getAccessibleRole();
15
+ const role = cast(widget).getAccessibleRole();
16
16
  if (role === Gtk.AccessibleRole.LABEL) {
17
- return getObject(widget.ptr, Gtk.Label).getLabel();
17
+ return cast(widget).getLabel();
18
18
  }
19
- return getObject(widget.ptr, Gtk.Button).getLabel();
19
+ return cast(widget).getLabel();
20
20
  };
21
21
  const printWidgetTree = (root, indent = 0) => {
22
22
  const prefix = " ".repeat(indent);
23
- const role = Gtk.AccessibleRole[asAccessible(root).getAccessibleRole()] ?? "UNKNOWN";
23
+ const role = Gtk.AccessibleRole[cast(root).getAccessibleRole()] ?? "UNKNOWN";
24
24
  const labelText = getWidgetLabel(root);
25
25
  const label = labelText ? ` label="${labelText}"` : "";
26
26
  let result = `${prefix}<${root.constructor.name} role=${role}${label}>\n`;
@@ -1,22 +1,22 @@
1
- import { getObject } from "@gtkx/ffi";
2
- import { AccessibleRole, CheckButton, ComboBox, DirectionType, DropDown, Editable, ListBox, ListBoxRow, ToggleButton, Widget, } from "@gtkx/ffi/gtk";
1
+ import { cast } from "@gtkx/ffi";
2
+ import { AccessibleRole, DirectionType, } from "@gtkx/ffi/gtk";
3
3
  import { fireEvent } from "./fire-event.js";
4
4
  import { tick } from "./timing.js";
5
- import { asAccessible, isEditable } from "./widget.js";
5
+ import { isEditable } from "./widget.js";
6
6
  const TOGGLEABLE_ROLES = new Set([AccessibleRole.CHECKBOX, AccessibleRole.RADIO, AccessibleRole.TOGGLE_BUTTON]);
7
7
  const isToggleable = (widget) => {
8
- const role = asAccessible(widget).getAccessibleRole();
8
+ const role = cast(widget).getAccessibleRole();
9
9
  return TOGGLEABLE_ROLES.has(role);
10
10
  };
11
11
  const click = async (element) => {
12
12
  if (isToggleable(element)) {
13
- const role = asAccessible(element).getAccessibleRole();
13
+ const role = cast(element).getAccessibleRole();
14
14
  if (role === AccessibleRole.CHECKBOX || role === AccessibleRole.RADIO) {
15
- const checkButton = getObject(element.ptr, CheckButton);
15
+ const checkButton = element;
16
16
  checkButton.setActive(!checkButton.getActive());
17
17
  }
18
18
  else {
19
- const toggleButton = getObject(element.ptr, ToggleButton);
19
+ const toggleButton = element;
20
20
  toggleButton.setActive(!toggleButton.getActive());
21
21
  }
22
22
  // Note: setActive() automatically emits the "toggled" signal, so we don't need to emit it manually
@@ -48,8 +48,7 @@ const tab = async (element, options) => {
48
48
  const direction = options?.shift ? DirectionType.TAB_BACKWARD : DirectionType.TAB_FORWARD;
49
49
  const root = element.getRoot();
50
50
  if (root) {
51
- const rootWidget = getObject(root.ptr, Widget);
52
- rootWidget.childFocus(direction);
51
+ cast(root).childFocus(direction);
53
52
  }
54
53
  await tick();
55
54
  };
@@ -57,7 +56,7 @@ const type = async (element, text) => {
57
56
  if (!isEditable(element)) {
58
57
  throw new Error("Cannot type into element: element is not editable (TEXT_BOX, SEARCH_BOX, or SPIN_BUTTON)");
59
58
  }
60
- const editable = getObject(element.ptr, Editable);
59
+ const editable = cast(element);
61
60
  const currentText = editable.getText();
62
61
  editable.setText(currentText + text);
63
62
  await tick();
@@ -66,20 +65,19 @@ const clear = async (element) => {
66
65
  if (!isEditable(element)) {
67
66
  throw new Error("Cannot clear element: element is not editable (TEXT_BOX, SEARCH_BOX, or SPIN_BUTTON)");
68
67
  }
69
- const editable = getObject(element.ptr, Editable);
70
- editable.setText("");
68
+ cast(element).setText("");
71
69
  await tick();
72
70
  };
73
71
  const SELECTABLE_ROLES = new Set([AccessibleRole.COMBO_BOX, AccessibleRole.LIST]);
74
72
  const isSelectable = (widget) => {
75
- const role = asAccessible(widget).getAccessibleRole();
73
+ const role = cast(widget).getAccessibleRole();
76
74
  return SELECTABLE_ROLES.has(role);
77
75
  };
78
76
  const selectOptions = async (element, values) => {
79
77
  if (!isSelectable(element)) {
80
78
  throw new Error("Cannot select options: element is not a selectable widget (COMBO_BOX or LIST)");
81
79
  }
82
- const role = asAccessible(element).getAccessibleRole();
80
+ const role = cast(element).getAccessibleRole();
83
81
  const valueArray = Array.isArray(values) ? values : [values];
84
82
  if (role === AccessibleRole.COMBO_BOX) {
85
83
  if (valueArray.length > 1) {
@@ -91,14 +89,14 @@ const selectOptions = async (element, values) => {
91
89
  }
92
90
  const isDropDown = element.constructor.name === "DropDown";
93
91
  if (isDropDown) {
94
- getObject(element.ptr, DropDown).setSelected(value);
92
+ element.setSelected(value);
95
93
  }
96
94
  else {
97
- getObject(element.ptr, ComboBox).setActive(value);
95
+ element.setActive(value);
98
96
  }
99
97
  }
100
98
  else if (role === AccessibleRole.LIST) {
101
- const listBox = getObject(element.ptr, ListBox);
99
+ const listBox = element;
102
100
  for (const value of valueArray) {
103
101
  if (typeof value !== "number") {
104
102
  throw new Error("ListBox selection requires numeric indices");
@@ -112,16 +110,16 @@ const selectOptions = async (element, values) => {
112
110
  await tick();
113
111
  };
114
112
  const deselectOptions = async (element, values) => {
115
- const role = asAccessible(element).getAccessibleRole();
113
+ const role = cast(element).getAccessibleRole();
116
114
  if (role !== AccessibleRole.LIST) {
117
115
  throw new Error("Cannot deselect options: only ListBox supports deselection");
118
116
  }
119
- const listBox = getObject(element.ptr, ListBox);
117
+ const listBox = element;
120
118
  const valueArray = Array.isArray(values) ? values : [values];
121
119
  for (const value of valueArray) {
122
120
  const row = listBox.getRowAtIndex(value);
123
121
  if (row) {
124
- listBox.unselectRow(getObject(row.ptr, ListBoxRow));
122
+ listBox.unselectRow(row);
125
123
  }
126
124
  }
127
125
  await tick();
package/dist/widget.d.ts CHANGED
@@ -1,5 +1,3 @@
1
1
  import type * as Gtk from "@gtkx/ffi/gtk";
2
- import { type Accessible } from "@gtkx/ffi/gtk";
3
- export declare const asAccessible: (widget: Gtk.Widget) => Accessible;
4
2
  export declare const isEditable: (widget: Gtk.Widget) => boolean;
5
3
  export declare const hasLabel: (widget: Gtk.Widget) => boolean;
package/dist/widget.js CHANGED
@@ -1,8 +1,8 @@
1
+ import { cast } from "@gtkx/ffi";
1
2
  import { AccessibleRole } from "@gtkx/ffi/gtk";
2
- export const asAccessible = (widget) => widget;
3
3
  const EDITABLE_ROLES = new Set([AccessibleRole.TEXT_BOX, AccessibleRole.SEARCH_BOX, AccessibleRole.SPIN_BUTTON]);
4
4
  export const isEditable = (widget) => {
5
- const role = asAccessible(widget).getAccessibleRole();
5
+ const role = cast(widget).getAccessibleRole();
6
6
  return EDITABLE_ROLES.has(role);
7
7
  };
8
8
  const LABEL_ROLES = new Set([
@@ -16,6 +16,6 @@ const LABEL_ROLES = new Set([
16
16
  AccessibleRole.MENU_ITEM_RADIO,
17
17
  ]);
18
18
  export const hasLabel = (widget) => {
19
- const role = asAccessible(widget).getAccessibleRole();
19
+ const role = cast(widget).getAccessibleRole();
20
20
  return LABEL_ROLES.has(role);
21
21
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gtkx/testing",
3
- "version": "0.2.7",
3
+ "version": "0.3.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.2.7",
36
- "@gtkx/react": "0.2.7",
37
- "@gtkx/native": "0.2.7"
35
+ "@gtkx/ffi": "0.3.0",
36
+ "@gtkx/native": "0.3.0",
37
+ "@gtkx/react": "0.3.0"
38
38
  },
39
39
  "scripts": {
40
40
  "build": "tsc -b && cp ../../README.md .",