@gtkx/testing 0.14.0 → 0.15.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/README.md CHANGED
@@ -80,11 +80,11 @@ render(<App />, "com.example.counter");
80
80
 
81
81
  Explore complete applications in the [`examples/`](./examples) directory:
82
82
 
83
- - **[browser](./examples/browser)** — Simple browser using WebKitWebView
84
83
  - **[gtk-demo](./examples/gtk-demo)** — Full replica of the official GTK demo app
85
84
  - **[hello-world](./examples/hello-world)** — Minimal application showing a counter
86
85
  - **[todo](./examples/todo)** — Full-featured todo application with Adwaita styling and testing
87
86
  - **[x-showcase](./examples/x-showcase)** — Showcase of all x.\* virtual components
87
+ - **[browser](./examples/browser)** — Simple browser using WebKitWebView
88
88
  - **[deploying](./examples/deploying)** — Example of packaging and distributing a GTKX app
89
89
 
90
90
  ## Documentation
@@ -1,5 +1,5 @@
1
+ import { Value } from "@gtkx/ffi/gobject";
1
2
  import type * as Gtk from "@gtkx/ffi/gtk";
2
- import type { Arg } from "@gtkx/native";
3
3
  /**
4
4
  * Emits a GTK signal on a widget or event controller.
5
5
  *
@@ -8,20 +8,21 @@ import type { Arg } from "@gtkx/native";
8
8
  *
9
9
  * @param element - The widget or event controller to emit the signal on
10
10
  * @param signalName - GTK signal name (e.g., "clicked", "activate", "drag-begin")
11
- * @param args - Additional signal arguments
11
+ * @param args - Additional signal arguments as GValues
12
12
  *
13
13
  * @example
14
14
  * ```tsx
15
15
  * import { fireEvent } from "@gtkx/testing";
16
+ * import { Value } from "@gtkx/ffi/gobject";
16
17
  *
17
18
  * // Emit signal on widget
18
19
  * await fireEvent(widget, "clicked");
19
20
  *
20
21
  * // Emit signal on gesture controller
21
22
  * const gesture = widget.observeControllers().getObject(0) as Gtk.GestureDrag;
22
- * await fireEvent(gesture, "drag-begin", { type: { type: "float", size: 64 }, value: 100 }, { type: { type: "float", size: 64 }, value: 100 });
23
+ * await fireEvent(gesture, "drag-begin", Value.newFromDouble(100), Value.newFromDouble(100));
23
24
  * ```
24
25
  *
25
26
  * @see {@link userEvent} for high-level user interactions
26
27
  */
27
- export declare const fireEvent: (element: Gtk.Widget | Gtk.EventController, signalName: string, ...args: Arg[]) => Promise<void>;
28
+ export declare const fireEvent: (element: Gtk.Widget | Gtk.EventController, signalName: string, ...args: Value[]) => Promise<void>;
@@ -1,4 +1,4 @@
1
- import { call } from "@gtkx/native";
1
+ import { signalEmitv, signalLookup, typeFromName, Value } from "@gtkx/ffi/gobject";
2
2
  import { tick } from "./timing.js";
3
3
  /**
4
4
  * Emits a GTK signal on a widget or event controller.
@@ -8,27 +8,27 @@ import { tick } from "./timing.js";
8
8
  *
9
9
  * @param element - The widget or event controller to emit the signal on
10
10
  * @param signalName - GTK signal name (e.g., "clicked", "activate", "drag-begin")
11
- * @param args - Additional signal arguments
11
+ * @param args - Additional signal arguments as GValues
12
12
  *
13
13
  * @example
14
14
  * ```tsx
15
15
  * import { fireEvent } from "@gtkx/testing";
16
+ * import { Value } from "@gtkx/ffi/gobject";
16
17
  *
17
18
  * // Emit signal on widget
18
19
  * await fireEvent(widget, "clicked");
19
20
  *
20
21
  * // Emit signal on gesture controller
21
22
  * const gesture = widget.observeControllers().getObject(0) as Gtk.GestureDrag;
22
- * await fireEvent(gesture, "drag-begin", { type: { type: "float", size: 64 }, value: 100 }, { type: { type: "float", size: 64 }, value: 100 });
23
+ * await fireEvent(gesture, "drag-begin", Value.newFromDouble(100), Value.newFromDouble(100));
23
24
  * ```
24
25
  *
25
26
  * @see {@link userEvent} for high-level user interactions
26
27
  */
27
28
  export const fireEvent = async (element, signalName, ...args) => {
28
- call("libgobject-2.0.so.0", "g_signal_emit_by_name", [
29
- { type: { type: "gobject", ownership: "borrowed" }, value: element.handle },
30
- { type: { type: "string", ownership: "borrowed" }, value: signalName },
31
- ...args,
32
- ], { type: "undefined" });
29
+ const gtype = typeFromName(element.constructor.glibTypeName);
30
+ const signalId = signalLookup(signalName, gtype);
31
+ const instanceValue = Value.newFromObject(element);
32
+ signalEmitv([instanceValue, ...args], signalId, 0, null);
33
33
  await tick();
34
34
  };
@@ -6,6 +6,13 @@ export type TabOptions = {
6
6
  /** Navigate backwards (Shift+Tab) instead of forwards */
7
7
  shift?: boolean;
8
8
  };
9
+ /**
10
+ * Pointer input actions for simulating mouse interactions.
11
+ *
12
+ * - `"click"` or `"[MouseLeft]"`: Full click (press + release)
13
+ * - `"down"` or `"[MouseLeft>]"`: Press and hold
14
+ * - `"up"` or `"[/MouseLeft]"`: Release
15
+ */
9
16
  export type PointerInput = "click" | "down" | "up" | "[MouseLeft]" | "[MouseLeft>]" | "[/MouseLeft]";
10
17
  /**
11
18
  * User interaction utilities for testing.
@@ -1,7 +1,7 @@
1
1
  import { getNativeObject } from "@gtkx/ffi";
2
2
  import * as Gdk from "@gtkx/ffi/gdk";
3
+ import { signalEmitv, signalLookup, typeFromName, Value } from "@gtkx/ffi/gobject";
3
4
  import * as Gtk from "@gtkx/ffi/gtk";
4
- import { call, createRef } from "@gtkx/native";
5
5
  import { fireEvent } from "./fire-event.js";
6
6
  import { tick } from "./timing.js";
7
7
  import { isEditable } from "./widget.js";
@@ -166,36 +166,18 @@ const getOrCreateController = (element, controllerType) => {
166
166
  element.addController(controller);
167
167
  return controller;
168
168
  };
169
- const SIGNALS_WITH_RETURN_VALUE = new Set(["key-pressed", "key-released"]);
170
- const emitSignal = (target, signalName, ...args) => {
171
- const signalArgs = args.map((arg) => {
172
- if (arg.type === "float") {
173
- return { type: { type: "float", size: 64 }, value: arg.value };
174
- }
175
- return { type: { type: "int", size: 32, unsigned: true }, value: arg.value };
176
- });
177
- const ffiArgs = [
178
- { type: { type: "gobject", ownership: "borrowed" }, value: target.handle },
179
- { type: { type: "string", ownership: "borrowed" }, value: signalName },
180
- ...signalArgs,
181
- ];
182
- if (SIGNALS_WITH_RETURN_VALUE.has(signalName)) {
183
- const returnRef = createRef(0);
184
- ffiArgs.push({
185
- type: { type: "ref", innerType: { type: "int", size: 32, unsigned: false } },
186
- value: returnRef,
187
- });
188
- }
189
- call("libgobject-2.0.so.0", "g_signal_emit_by_name", ffiArgs, { type: "undefined" });
169
+ const getSignalId = (target, signalName) => {
170
+ const gtype = typeFromName(target.constructor.glibTypeName);
171
+ return signalLookup(signalName, gtype);
190
172
  };
191
173
  const hover = async (element) => {
192
174
  const controller = getOrCreateController(element, Gtk.EventControllerMotion);
193
- emitSignal(controller, "enter", { type: "float", value: 0 }, { type: "float", value: 0 });
175
+ signalEmitv([Value.newFromObject(controller), Value.newFromDouble(0), Value.newFromDouble(0)], getSignalId(controller, "enter"), 0, null);
194
176
  await tick();
195
177
  };
196
178
  const unhover = async (element) => {
197
179
  const controller = getOrCreateController(element, Gtk.EventControllerMotion);
198
- emitSignal(controller, "leave");
180
+ signalEmitv([Value.newFromObject(controller)], getSignalId(controller, "leave"), 0, null);
199
181
  await tick();
200
182
  };
201
183
  const KEY_MAP = {
@@ -261,7 +243,13 @@ const keyboard = async (element, input) => {
261
243
  const actions = parseKeyboardInput(input);
262
244
  for (const action of actions) {
263
245
  const signalName = action.press ? "key-pressed" : "key-released";
264
- emitSignal(controller, signalName, { type: "int", value: action.keyval }, { type: "int", value: 0 }, { type: "int", value: 0 });
246
+ const returnValue = Value.newFromBoolean(false);
247
+ signalEmitv([
248
+ Value.newFromObject(controller),
249
+ Value.newFromUint(action.keyval),
250
+ Value.newFromUint(0),
251
+ Value.newFromUint(0),
252
+ ], getSignalId(controller, signalName), 0, returnValue);
265
253
  if (action.press && action.keyval === Gdk.KEY_Return && isEditable(element)) {
266
254
  await fireEvent(element, "activate");
267
255
  }
@@ -270,15 +258,27 @@ const keyboard = async (element, input) => {
270
258
  };
271
259
  const pointer = async (element, input) => {
272
260
  const controller = getOrCreateController(element, Gtk.GestureClick);
261
+ const pressedArgs = [
262
+ Value.newFromObject(controller),
263
+ Value.newFromInt(1),
264
+ Value.newFromDouble(0),
265
+ Value.newFromDouble(0),
266
+ ];
267
+ const releasedArgs = [
268
+ Value.newFromObject(controller),
269
+ Value.newFromInt(1),
270
+ Value.newFromDouble(0),
271
+ Value.newFromDouble(0),
272
+ ];
273
273
  if (input === "[MouseLeft]" || input === "click") {
274
- emitSignal(controller, "pressed", { type: "int", value: 1 }, { type: "float", value: 0 }, { type: "float", value: 0 });
275
- emitSignal(controller, "released", { type: "int", value: 1 }, { type: "float", value: 0 }, { type: "float", value: 0 });
274
+ signalEmitv(pressedArgs, getSignalId(controller, "pressed"), 0, null);
275
+ signalEmitv(releasedArgs, getSignalId(controller, "released"), 0, null);
276
276
  }
277
277
  else if (input === "[MouseLeft>]" || input === "down") {
278
- emitSignal(controller, "pressed", { type: "int", value: 1 }, { type: "float", value: 0 }, { type: "float", value: 0 });
278
+ signalEmitv(pressedArgs, getSignalId(controller, "pressed"), 0, null);
279
279
  }
280
280
  else if (input === "[/MouseLeft]" || input === "up") {
281
- emitSignal(controller, "released", { type: "int", value: 1 }, { type: "float", value: 0 }, { type: "float", value: 0 });
281
+ signalEmitv(releasedArgs, getSignalId(controller, "released"), 0, null);
282
282
  }
283
283
  await tick();
284
284
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gtkx/testing",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "description": "Testing utilities for GTKX applications",
5
5
  "keywords": [
6
6
  "gtkx",
@@ -36,14 +36,13 @@
36
36
  "dist"
37
37
  ],
38
38
  "dependencies": {
39
- "@gtkx/ffi": "0.14.0",
40
- "@gtkx/native": "0.14.0",
41
- "@gtkx/react": "0.14.0"
39
+ "@gtkx/ffi": "0.15.0",
40
+ "@gtkx/react": "0.15.0"
42
41
  },
43
42
  "devDependencies": {
44
43
  "@types/react-reconciler": "^0.32.3",
45
44
  "react-reconciler": "^0.33.0",
46
- "@gtkx/vitest": "0.14.0"
45
+ "@gtkx/vitest": "0.15.0"
47
46
  },
48
47
  "scripts": {
49
48
  "build": "tsc -b && cp ../../README.md .",