@gtkx/testing 0.21.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 +137 -34
  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 -33
  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 +56 -14
  160. package/src/matchers.ts +200 -0
  161. package/src/pretty-widget.ts +99 -138
  162. package/src/queries.ts +320 -420
  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 -81
  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
package/README.md CHANGED
@@ -1,70 +1,173 @@
1
1
  <p align="center">
2
- <img src="https://raw.githubusercontent.com/eugeniodepalo/gtkx/main/logo.svg" alt="GTKX" width="100" height="100">
2
+ <img src="https://raw.githubusercontent.com/gtkx-org/gtkx/main/logo.svg" alt="GTKX" width="100" />
3
3
  </p>
4
4
 
5
5
  <h1 align="center">GTKX</h1>
6
6
 
7
7
  <p align="center">
8
- <strong>Linux application development for the modern age powered by GTK4 and React</strong>
8
+ The React framework for Linux.<br />
9
+ Build GTK4 and Adwaita apps in TypeScript, with React components and hooks driving GNOME's own widgets. What you ship is a GNOME app.
9
10
  </p>
10
11
 
11
12
  <p align="center">
12
- <a href="https://www.npmjs.com/package/@gtkx/react"><img src="https://img.shields.io/npm/v/@gtkx/react.svg" alt="npm version"></a>
13
- <a href="https://github.com/gtkx-org/gtkx/actions"><img src="https://img.shields.io/github/actions/workflow/status/eugeniodepalo/gtkx/ci.yml" alt="CI"></a>
14
- <a href="https://github.com/gtkx-org/gtkx/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MPL--2.0-blue.svg" alt="License"></a>
15
- <a href="https://github.com/gtkx-org/gtkx/discussions"><img src="https://img.shields.io/badge/discussions-GitHub-blue" alt="GitHub Discussions"></a>
13
+ <a href="https://www.npmjs.com/package/create-gtkx"><img src="https://img.shields.io/npm/v/create-gtkx?color=cb3837&logo=npm&label=create-gtkx" alt="npm version" /></a>
14
+ <a href="https://www.npmjs.com/package/create-gtkx"><img src="https://img.shields.io/npm/dm/create-gtkx?color=cb3837&logo=npm&label=downloads" alt="npm downloads" /></a>
15
+ <img src="https://img.shields.io/badge/node-%E2%89%A524-339933?logo=node.js&logoColor=white" alt="Node >= 24" />
16
+ <a href="https://github.com/gtkx-org/gtkx/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MPL--2.0-blue.svg" alt="License: MPL-2.0" /></a>
17
+ <a href="https://github.com/gtkx-org/gtkx/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/gtkx-org/gtkx/ci.yml?branch=main&logo=github&label=CI" alt="CI status" /></a>
18
+ <img src="https://img.shields.io/badge/TypeScript-strict-3178c6?logo=typescript&logoColor=white" alt="TypeScript" />
19
+ </p>
20
+
21
+ <p align="center">
22
+ <a href="https://gtkx.dev">Homepage</a> &middot;
23
+ <a href="https://gtkx.dev/guide/why-gtkx">Documentation</a> &middot;
24
+ <a href="https://github.com/gtkx-org/gtkx/tree/main/examples">Examples</a> &middot;
25
+ <a href="https://github.com/gtkx-org/gtkx/blob/main/CONTRIBUTING.md">Contributing</a>
16
26
  </p>
17
27
 
18
28
  ---
19
29
 
30
+ GTKX generates fully typed bindings for the entire GTK4 and Adwaita surface directly from GObject-Introspection. On top of those bindings you get the React programming model: components and hooks driving GObject instances, with Fast Refresh while you develop.
31
+
20
32
  <p align="center">
21
- <img src="https://raw.githubusercontent.com/eugeniodepalo/gtkx/main/demo.gif" alt="GTKX Demo" width="100%">
33
+ <img src="https://raw.githubusercontent.com/gtkx-org/gtkx/main/examples/tutorial/assets/screenshot.png" alt="The Tasks app: an Adwaita window with a sidebar of smart views and colored lists on the left, and a boxed task list on the right." />
22
34
  </p>
23
35
 
24
- ---
36
+ <p align="center">
37
+ <em>The Tasks app you build in the <a href="https://gtkx.dev/tutorial/">tutorial</a>.</em>
38
+ </p>
39
+
40
+ ## Demo
41
+
42
+ The intrinsic elements in this snippet render GTK4 widgets, and ordinary React hooks and events drive them:
43
+
44
+ ```tsx
45
+ import * as Gtk from "@gtkx/gi/gtk";
46
+ import { GtkApplication, GtkApplicationWindow, GtkBox, GtkButton, GtkLabel } from "@gtkx/jsx/gtk";
47
+ import { createRoot, quit } from "@gtkx/react";
48
+ import { useState } from "react";
49
+
50
+ const Counter = () => {
51
+ const [count, setCount] = useState(0);
52
+
53
+ return (
54
+ <GtkApplicationWindow
55
+ title="Hello GTKX"
56
+ defaultWidth={400}
57
+ defaultHeight={300}
58
+ onCloseRequest={quit}
59
+ >
60
+ <GtkBox
61
+ orientation={Gtk.Orientation.VERTICAL}
62
+ spacing={20}
63
+ marginTop={40}
64
+ marginBottom={40}
65
+ marginStart={40}
66
+ marginEnd={40}
67
+ valign={Gtk.Align.CENTER}
68
+ halign={Gtk.Align.CENTER}
69
+ >
70
+ <GtkLabel cssClasses={["title-1"]}>Welcome to GTKX!</GtkLabel>
71
+ <GtkLabel cssClasses={["title-2"]}>{`Count: ${count}`}</GtkLabel>
72
+ <GtkButton
73
+ label="Increment"
74
+ onClicked={() => setCount((c) => c + 1)}
75
+ cssClasses={["suggested-action", "pill"]}
76
+ />
77
+ </GtkBox>
78
+ </GtkApplicationWindow>
79
+ );
80
+ };
81
+
82
+ const App = () => (
83
+ <GtkApplication>
84
+ <Counter />
85
+ </GtkApplication>
86
+ );
87
+
88
+ createRoot().render(<App />);
89
+ ```
90
+
91
+ This is the [`hello-world`](https://github.com/gtkx-org/gtkx/tree/main/examples/hello-world) example, with `app.tsx` and `index.tsx` combined into a single snippet. `@gtkx/gi` and `@gtkx/jsx` are per-project bindings generated by the CLI, not packages you install from npm.
92
+
93
+ ## Why GTKX
94
+
95
+ ### A declarative layer for the GNOME stack
96
+
97
+ GTK4 is mature, and GtkBuilder XML can lay out a static interface, but nothing re-renders that interface when your application state changes, and nothing hot-reloads it as you work. GTKX adds that missing layer, and the tooling around it, on top of the stack you already know:
98
+
99
+ - a React reconciler that exposes every GObject as a JSX element,
100
+ - a CLI for scaffolding, development, and production builds,
101
+ - a dev server with Fast Refresh that patches your running UI in place,
102
+ - CSS-in-JS styling and high-level list, grid, and dialog components,
103
+ - a Testing Library-style API for querying and driving your widgets in tests,
104
+ - and a Model Context Protocol (MCP) server that exposes your live app to AI agents.
105
+
106
+ ### The full GNOME API surface
107
+
108
+ React Native and similar frameworks hide the native toolkit so one API can run everywhere. GTKX exposes it: GTK4, Adwaita, and any other GObject-Introspection library on your system. Linux-only by design.
109
+
110
+ ### Why Node.js, and why generated bindings
111
+
112
+ GTKX runs on Node.js, which puts native modules, the npm ecosystem, and the tooling built for Node.js APIs within reach. GJS is GNOME's own runtime, built on SpiderMonkey rather than V8; node-gtk runs on Node.js but is lightly maintained, on the older nan/V8 ABI rather than N-API, and still centered on GTK3. The [why-gtkx guide](https://gtkx.dev/guide/why-gtkx) covers the comparison in full.
25
113
 
26
- GTKX is a modern framework for building native Linux applications using React and GTK. It provides the full range of GTK4, GLib, and Node.js APIs, allowing you to create rich, performant desktop applications with the tools and libraries you already know.
114
+ GTKX generates the TypeScript types and the native FFI calls from the same GObject-Introspection data, so the types cannot drift from the calls they back. Codegen covers the whole GTK4 and Adwaita surface.
27
115
 
28
- ## Features
116
+ At runtime, the native Rust core calls straight into the system GTK4, Adwaita, and GLib libraries through libffi, without loading libgirepository at all.
29
117
 
30
- - **React 19** — Hooks, concurrent features, and the component model you know
31
- - **Fully native Node.js environment** - Runs on vanilla Node.js, with the help of a Neon native module
32
- - **TypeScript first** — Full type safety with auto-generated bindings
33
- - **Rich GLib support** — Provides bindings for most modern GLib/GObject libraries, including Adwaita
34
- - **HMR** — Fast refresh during development powered by Vite
35
- - **CSS-in-JS styling** — Easy styling with GTK CSS powered by Emotion
36
- - **Testing library** — Testing Library-inspired API for testing components and E2E
118
+ ## Quick start
37
119
 
38
- ## Quick Start
120
+ GTKX is Linux-only and needs Node.js 24 or later. See [Requirements](#requirements).
39
121
 
40
- ```bash
41
- npx @gtkx/cli create my-app
122
+ Scaffold a new app with the `create-gtkx` initializer:
123
+
124
+ ```sh
125
+ npm create gtkx@rc
126
+ ```
127
+
128
+ The same command works with other package managers: `pnpm create gtkx@rc` or `yarn create gtkx@rc`.
129
+
130
+ Then run your new app:
131
+
132
+ ```sh
42
133
  cd my-app
43
134
  npm run dev
44
135
  ```
45
136
 
46
- ## Examples
137
+ To go further, follow the [tutorial](https://gtkx.dev/tutorial/).
47
138
 
48
- Explore complete applications in the [`examples/`](./examples) directory:
139
+ ## Documentation
49
140
 
50
- - **[hello-world](./examples/hello-world)** Minimal application showing a counter
51
- - **[gtk-demo](./examples/gtk-demo)** — Full replica of the official GTK demo app
52
- - **[tutorial](./examples/tutorial)** — Notes app from the tutorial with GSettings and Adwaita
53
- - **[browser](./examples/browser)** — Simple browser using WebKitWebView
141
+ The documentation at **[gtkx.dev](https://gtkx.dev)** includes a step-by-step tutorial that builds a complete GNOME app, from scaffolding to packaging and shipping, plus guides and a full API reference.
54
142
 
55
- ## Documentation
143
+ **[Read the docs &rarr;](https://gtkx.dev/guide/why-gtkx)**
56
144
 
57
- Visit [https://gtkx.dev](https://gtkx.dev) for the full documentation.
145
+ ## Requirements
58
146
 
59
- ## Contributing
147
+ GTKX is Linux-only. You need:
60
148
 
61
- Contributions are welcome! Please see the [contributing guidelines](./CONTRIBUTING.md).
149
+ - Linux with the GTK4 (4.20 or later), Adwaita (1.8 or later), and GLib development libraries
150
+ - Node.js 24 or later
62
151
 
63
- ## Community
152
+ The `@gtkx/native` addon ships prebuilt for x64 and arm64 glibc Linux; other targets need to build it from the GTKX repository, which requires a Rust toolchain.
153
+
154
+ ## Examples
155
+
156
+ Explore the [example apps](https://github.com/gtkx-org/gtkx/tree/main/examples):
157
+
158
+ - [`hello-world`](https://github.com/gtkx-org/gtkx/tree/main/examples/hello-world): the counter above.
159
+ - [`gtk-demo`](https://github.com/gtkx-org/gtkx/tree/main/examples/gtk-demo): a React port of the official GTK4 widget showcase, covering lists, dialogs, gestures, CSS, and OpenGL.
160
+ - [`browser`](https://github.com/gtkx-org/gtkx/tree/main/examples/browser): a WebKitWebView-based web browser.
161
+ - [`tutorial`](https://github.com/gtkx-org/gtkx/tree/main/examples/tutorial): the Tasks app the documentation builds.
162
+
163
+ ## Status
164
+
165
+ GTKX 1.0 is at the release candidate stage.
166
+
167
+ ## Contributing
64
168
 
65
- - [GitHub Discussions](https://github.com/gtkx-org/gtkx/discussions) Questions, ideas, and general discussion
66
- - [Issue Tracker](https://github.com/gtkx-org/gtkx/issues) — Bug reports and feature requests
169
+ Contributions are welcome. See [CONTRIBUTING.md](https://github.com/gtkx-org/gtkx/blob/main/CONTRIBUTING.md), the [Code of Conduct](https://github.com/gtkx-org/gtkx/blob/main/CODE_OF_CONDUCT.md), and the [security policy](https://github.com/gtkx-org/gtkx/blob/main/SECURITY.md). Building the repo needs Node.js 24 or later, pnpm, and a Rust toolchain.
67
170
 
68
171
  ## License
69
172
 
70
- [MPL-2.0](./LICENSE)
173
+ GTKX is licensed under [MPL-2.0](https://github.com/gtkx-org/gtkx/blob/main/LICENSE).
package/dist/act.d.ts ADDED
@@ -0,0 +1,19 @@
1
+ declare global {
2
+ var IS_REACT_ACT_ENVIRONMENT: boolean | undefined;
3
+ }
4
+ export declare const getIsReactActEnvironment: () => boolean | undefined;
5
+ export declare const setIsReactActEnvironment: (value: boolean | undefined) => void;
6
+ type ActCallback<T> = () => T | PromiseLike<T>;
7
+ type ActImplementation = <T>(callback: ActCallback<T>) => PromiseLike<T>;
8
+ export declare const runWithActEnvironment: <T>(forced: boolean, fn: () => T | PromiseLike<T>) => T | PromiseLike<T>;
9
+ /**
10
+ * Runs a callback inside React's act environment, flushing pending state
11
+ * updates and effects, and resolves once the work has settled.
12
+ *
13
+ * @param callback Work to run within the act environment.
14
+ * @returns A promise that resolves with the callback's result after updates flush.
15
+ */
16
+ export declare const act: ActImplementation;
17
+ export declare const runInAct: (callback: () => unknown) => Promise<void>;
18
+ export {};
19
+ //# sourceMappingURL=act.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"act.d.ts","sourceRoot":"","sources":["../src/act.ts"],"names":[],"mappings":"AAEA,OAAO,CAAC,MAAM,CAAC;IACX,IAAI,wBAAwB,EAAE,OAAO,GAAG,SAAS,CAAC;CACrD;AAOD,eAAO,MAAM,wBAAwB,QAAO,OAAO,GAAG,SAAqD,CAAC;AAE5G,eAAO,MAAM,wBAAwB,UAAW,OAAO,GAAG,SAAS,KAAG,IAErE,CAAC;AAEF,KAAK,WAAW,CAAC,CAAC,IAAI,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;AAC/C,KAAK,iBAAiB,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC;AAKzE,eAAO,MAAM,qBAAqB,GAAI,CAAC,UAAU,OAAO,MAAM,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,KAAG,CAAC,GAAG,WAAW,CAAC,CAAC,CAuBzG,CAAC;AAWF;;;;;;GAMG;AACH,eAAO,MAAM,GAAG,EAAE,iBAA+D,CAAC;AAElF,eAAO,MAAM,QAAQ,aAAc,MAAM,OAAO,KAAG,OAAO,CAAC,IAAI,CACC,CAAC"}
package/dist/act.js ADDED
@@ -0,0 +1,48 @@
1
+ import { act as reactAct } from "react";
2
+ const getGlobalThis = () => {
3
+ if (typeof globalThis !== "undefined")
4
+ return globalThis;
5
+ throw new Error("unable to locate global object");
6
+ };
7
+ export const getIsReactActEnvironment = () => getGlobalThis().IS_REACT_ACT_ENVIRONMENT;
8
+ export const setIsReactActEnvironment = (value) => {
9
+ getGlobalThis().IS_REACT_ACT_ENVIRONMENT = value;
10
+ };
11
+ const isThenable = (value) => value !== null && typeof value === "object" && typeof value.then === "function";
12
+ export const runWithActEnvironment = (forced, fn) => {
13
+ const previousActEnvironment = getIsReactActEnvironment();
14
+ setIsReactActEnvironment(forced);
15
+ try {
16
+ const result = fn();
17
+ if (isThenable(result)) {
18
+ return Promise.resolve(result).then((value) => {
19
+ setIsReactActEnvironment(previousActEnvironment);
20
+ return value;
21
+ }, (error) => {
22
+ setIsReactActEnvironment(previousActEnvironment);
23
+ throw error;
24
+ });
25
+ }
26
+ setIsReactActEnvironment(previousActEnvironment);
27
+ return result;
28
+ }
29
+ catch (error) {
30
+ setIsReactActEnvironment(previousActEnvironment);
31
+ throw error;
32
+ }
33
+ };
34
+ const withGlobalActEnvironment = (actImplementation) => (callback) => {
35
+ const settled = runWithActEnvironment(true, () => actImplementation(() => callback()));
36
+ return Promise.resolve(settled);
37
+ };
38
+ const actImplementation = reactAct;
39
+ /**
40
+ * Runs a callback inside React's act environment, flushing pending state
41
+ * updates and effects, and resolves once the work has settled.
42
+ *
43
+ * @param callback Work to run within the act environment.
44
+ * @returns A promise that resolves with the callback's result after updates flush.
45
+ */
46
+ export const act = withGlobalActEnvironment(actImplementation);
47
+ export const runInAct = (callback) => Promise.resolve(act(() => callback())).then(() => undefined);
48
+ //# sourceMappingURL=act.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"act.js","sourceRoot":"","sources":["../src/act.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,IAAI,QAAQ,EAAE,MAAM,OAAO,CAAC;AAMxC,MAAM,aAAa,GAAG,GAAsB,EAAE;IAC1C,IAAI,OAAO,UAAU,KAAK,WAAW;QAAE,OAAO,UAAU,CAAC;IACzD,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;AACtD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAwB,EAAE,CAAC,aAAa,EAAE,CAAC,wBAAwB,CAAC;AAE5G,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,KAA0B,EAAQ,EAAE;IACzE,aAAa,EAAE,CAAC,wBAAwB,GAAG,KAAK,CAAC;AACrD,CAAC,CAAC;AAKF,MAAM,UAAU,GAAG,CAAI,KAAc,EAA2B,EAAE,CAC9D,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAQ,KAAwB,CAAC,IAAI,KAAK,UAAU,CAAC;AAExG,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAI,MAAe,EAAE,EAA4B,EAAsB,EAAE;IAC1G,MAAM,sBAAsB,GAAG,wBAAwB,EAAE,CAAC;IAC1D,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC;QACD,MAAM,MAAM,GAAG,EAAE,EAAE,CAAC;QACpB,IAAI,UAAU,CAAI,MAAM,CAAC,EAAE,CAAC;YACxB,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAC/B,CAAC,KAAK,EAAE,EAAE;gBACN,wBAAwB,CAAC,sBAAsB,CAAC,CAAC;gBACjD,OAAO,KAAK,CAAC;YACjB,CAAC,EACD,CAAC,KAAK,EAAE,EAAE;gBACN,wBAAwB,CAAC,sBAAsB,CAAC,CAAC;gBACjD,MAAM,KAAK,CAAC;YAChB,CAAC,CACJ,CAAC;QACN,CAAC;QACD,wBAAwB,CAAC,sBAAsB,CAAC,CAAC;QACjD,OAAO,MAAM,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,wBAAwB,CAAC,sBAAsB,CAAC,CAAC;QACjD,MAAM,KAAK,CAAC;IAChB,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,wBAAwB,GAC1B,CAAC,iBAAoC,EAAE,EAAE,CACzC,CAAI,QAAwB,EAAkB,EAAE;IAC5C,MAAM,OAAO,GAAG,qBAAqB,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IACvF,OAAO,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AACpC,CAAC,CAAC;AAEN,MAAM,iBAAiB,GAAsB,QAA6B,CAAC;AAE3E;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,GAAG,GAAsB,wBAAwB,CAAC,iBAAiB,CAAC,CAAC;AAElF,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,QAAuB,EAAiB,EAAE,CAC/D,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC","sourcesContent":["import { act as reactAct } from \"react\";\n\ndeclare global {\n var IS_REACT_ACT_ENVIRONMENT: boolean | undefined;\n}\n\nconst getGlobalThis = (): typeof globalThis => {\n if (typeof globalThis !== \"undefined\") return globalThis;\n throw new Error(\"unable to locate global object\");\n};\n\nexport const getIsReactActEnvironment = (): boolean | undefined => getGlobalThis().IS_REACT_ACT_ENVIRONMENT;\n\nexport const setIsReactActEnvironment = (value: boolean | undefined): void => {\n getGlobalThis().IS_REACT_ACT_ENVIRONMENT = value;\n};\n\ntype ActCallback<T> = () => T | PromiseLike<T>;\ntype ActImplementation = <T>(callback: ActCallback<T>) => PromiseLike<T>;\n\nconst isThenable = <T>(value: unknown): value is PromiseLike<T> =>\n value !== null && typeof value === \"object\" && typeof (value as PromiseLike<T>).then === \"function\";\n\nexport const runWithActEnvironment = <T>(forced: boolean, fn: () => T | PromiseLike<T>): T | PromiseLike<T> => {\n const previousActEnvironment = getIsReactActEnvironment();\n setIsReactActEnvironment(forced);\n try {\n const result = fn();\n if (isThenable<T>(result)) {\n return Promise.resolve(result).then(\n (value) => {\n setIsReactActEnvironment(previousActEnvironment);\n return value;\n },\n (error) => {\n setIsReactActEnvironment(previousActEnvironment);\n throw error;\n },\n );\n }\n setIsReactActEnvironment(previousActEnvironment);\n return result;\n } catch (error) {\n setIsReactActEnvironment(previousActEnvironment);\n throw error;\n }\n};\n\nconst withGlobalActEnvironment =\n (actImplementation: ActImplementation) =>\n <T>(callback: ActCallback<T>): PromiseLike<T> => {\n const settled = runWithActEnvironment(true, () => actImplementation(() => callback()));\n return Promise.resolve(settled);\n };\n\nconst actImplementation: ActImplementation = reactAct as ActImplementation;\n\n/**\n * Runs a callback inside React's act environment, flushing pending state\n * updates and effects, and resolves once the work has settled.\n *\n * @param callback Work to run within the act environment.\n * @returns A promise that resolves with the callback's result after updates flush.\n */\nexport const act: ActImplementation = withGlobalActEnvironment(actImplementation);\n\nexport const runInAct = (callback: () => unknown): Promise<void> =>\n Promise.resolve(act(() => callback())).then(() => undefined);\n"]}
@@ -0,0 +1,32 @@
1
+ import type * as Gtk from "@gtkx/gi/gtk";
2
+ import type { ReactNode } from "react";
3
+ import type { builtinQueries } from "./queries.js";
4
+ import type { Container } from "./traversal.js";
5
+ import type { BoundCustomQueries, DebugUtilities, QueryMap } from "./types.js";
6
+ /**
7
+ * The set of built-in queries (getBy, findBy, queryBy, and their All variants)
8
+ * bound to a specific container.
9
+ */
10
+ export type BoundQueries = BoundCustomQueries<typeof builtinQueries>;
11
+ /**
12
+ * The global screen object's shape: built-in queries scoped to the current
13
+ * toplevels, plus debug utilities.
14
+ */
15
+ export type Screen = BoundQueries & DebugUtilities;
16
+ /**
17
+ * The result of a render call: queries scoped to the rendered tree, debug
18
+ * utilities, and controls for updating or tearing down the render.
19
+ *
20
+ * @typeParam Q Custom queries provided at render time, merged with the built-in ones.
21
+ */
22
+ export type RenderResult<Q extends QueryMap = Record<never, never>> = BoundQueries & BoundCustomQueries<Q> & DebugUtilities & {
23
+ /** The top-level widget the element was rendered into. */
24
+ container: Gtk.Widget;
25
+ /** The root the queries are scoped to (defaults to all toplevels). */
26
+ baseElement: Container;
27
+ /** Unmounts the rendered tree and disposes its resources. */
28
+ unmount: () => Promise<void>;
29
+ /** Re-renders the tree with a new element, reusing the same root. */
30
+ rerender: (element: ReactNode) => Promise<void>;
31
+ };
32
+ //# sourceMappingURL=bound-queries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bound-queries.d.ts","sourceRoot":"","sources":["../src/bound-queries.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,GAAG,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE/E;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,kBAAkB,CAAC,OAAO,cAAc,CAAC,CAAC;AAErE;;;GAGG;AACH,MAAM,MAAM,MAAM,GAAG,YAAY,GAAG,cAAc,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,QAAQ,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,YAAY,GAC9E,kBAAkB,CAAC,CAAC,CAAC,GACrB,cAAc,GAAG;IACb,0DAA0D;IAC1D,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC;IACtB,sEAAsE;IACtE,WAAW,EAAE,SAAS,CAAC;IACvB,6DAA6D;IAC7D,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,qEAAqE;IACrE,QAAQ,EAAE,CAAC,OAAO,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=bound-queries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bound-queries.js","sourceRoot":"","sources":["../src/bound-queries.ts"],"names":[],"mappings":"","sourcesContent":["import type * as Gtk from \"@gtkx/gi/gtk\";\nimport type { ReactNode } from \"react\";\nimport type { builtinQueries } from \"./queries.js\";\nimport type { Container } from \"./traversal.js\";\nimport type { BoundCustomQueries, DebugUtilities, QueryMap } from \"./types.js\";\n\n/**\n * The set of built-in queries (getBy, findBy, queryBy, and their All variants)\n * bound to a specific container.\n */\nexport type BoundQueries = BoundCustomQueries<typeof builtinQueries>;\n\n/**\n * The global screen object's shape: built-in queries scoped to the current\n * toplevels, plus debug utilities.\n */\nexport type Screen = BoundQueries & DebugUtilities;\n\n/**\n * The result of a render call: queries scoped to the rendered tree, debug\n * utilities, and controls for updating or tearing down the render.\n *\n * @typeParam Q Custom queries provided at render time, merged with the built-in ones.\n */\nexport type RenderResult<Q extends QueryMap = Record<never, never>> = BoundQueries &\n BoundCustomQueries<Q> &\n DebugUtilities & {\n /** The top-level widget the element was rendered into. */\n container: Gtk.Widget;\n /** The root the queries are scoped to (defaults to all toplevels). */\n baseElement: Container;\n /** Unmounts the rendered tree and disposes its resources. */\n unmount: () => Promise<void>;\n /** Re-renders the tree with a new element, reusing the same root. */\n rerender: (element: ReactNode) => Promise<void>;\n };\n"]}
@@ -0,0 +1,16 @@
1
+ import type * as Gtk from "@gtkx/gi/gtk";
2
+ import { type Method } from "./suggestions.js";
3
+ import type { Container } from "./traversal.js";
4
+ export type QueryAllBy<Args extends unknown[]> = (container: Container, ...args: Args) => Gtk.Widget[];
5
+ type MultipleErrorBuilder<Args extends unknown[]> = (container: Container, matches: Gtk.Widget[], ...args: Args) => Error;
6
+ type MissingErrorBuilder<Args extends unknown[]> = (container: Container, ...args: Args) => Error;
7
+ export type BuiltQueries<Args extends unknown[]> = {
8
+ queryBy: (container: Container, ...args: Args) => Gtk.Widget | null;
9
+ getAllBy: QueryAllBy<Args>;
10
+ getBy: (container: Container, ...args: Args) => Gtk.Widget;
11
+ findAllBy: (container: Container, ...args: Args) => Promise<Gtk.Widget[]>;
12
+ findBy: (container: Container, ...args: Args) => Promise<Gtk.Widget>;
13
+ };
14
+ export declare const buildQueries: <Args extends unknown[]>(queryName: Method, queryAllBy: QueryAllBy<Args>, getMultipleError: MultipleErrorBuilder<Args>, getMissingError: MissingErrorBuilder<Args>) => BuiltQueries<Args>;
15
+ export {};
16
+ //# sourceMappingURL=build-queries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-queries.d.ts","sourceRoot":"","sources":["../src/build-queries.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,GAAG,MAAM,cAAc,CAAC;AAGzC,OAAO,EAAqB,KAAK,MAAM,EAAgB,MAAM,kBAAkB,CAAC;AAChF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAIhD,MAAM,MAAM,UAAU,CAAC,IAAI,SAAS,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,GAAG,CAAC,MAAM,EAAE,CAAC;AAEvG,KAAK,oBAAoB,CAAC,IAAI,SAAS,OAAO,EAAE,IAAI,CAChD,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,EACrB,GAAG,IAAI,EAAE,IAAI,KACZ,KAAK,CAAC;AACX,KAAK,mBAAmB,CAAC,IAAI,SAAS,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,KAAK,CAAC;AAElG,MAAM,MAAM,YAAY,CAAC,IAAI,SAAS,OAAO,EAAE,IAAI;IAC/C,OAAO,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC;IACpE,QAAQ,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;IAC3B,KAAK,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,GAAG,CAAC,MAAM,CAAC;IAC3D,SAAS,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1E,MAAM,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;CACxE,CAAC;AAyHF,eAAO,MAAM,YAAY,GAAI,IAAI,SAAS,OAAO,EAAE,aACpC,MAAM,cACL,UAAU,CAAC,IAAI,CAAC,oBACV,oBAAoB,CAAC,IAAI,CAAC,mBAC3B,mBAAmB,CAAC,IAAI,CAAC,KAC3C,YAAY,CAAC,IAAI,CAmCnB,CAAC"}
@@ -0,0 +1,103 @@
1
+ import { getConfig } from "./config.js";
2
+ import { runWithExpensiveErrorDiagnosticsDisabled, suggestionError } from "./errors.js";
3
+ import { getSuggestedQuery } from "./suggestions.js";
4
+ import { waitFor } from "./wait-for.js";
5
+ const extractWaitForOptions = (args) => {
6
+ const last = args[args.length - 1];
7
+ if (last && typeof last === "object" && !(last instanceof RegExp)) {
8
+ const { timeout, interval, onTimeout } = last;
9
+ return { timeout, interval, onTimeout };
10
+ }
11
+ return {};
12
+ };
13
+ const extractSuggestOption = (args) => {
14
+ const last = args[args.length - 1];
15
+ if (last && typeof last === "object" && !(last instanceof RegExp)) {
16
+ return last.suggest;
17
+ }
18
+ return undefined;
19
+ };
20
+ const maybeThrowSuggestion = (options) => {
21
+ const { container, match, queryName, variant, suggest } = options;
22
+ const shouldSuggest = suggest ?? getConfig().throwSuggestions;
23
+ if (!shouldSuggest)
24
+ return;
25
+ const suggestion = getSuggestedQuery(match, variant);
26
+ if (suggestion && suggestion.queryName !== queryName) {
27
+ throw suggestionError(suggestion.toString(), container);
28
+ }
29
+ };
30
+ const reRunForDiagnostics = (query, container, args, fallback) => {
31
+ try {
32
+ query(container, ...args);
33
+ }
34
+ catch (error) {
35
+ if (error instanceof Error)
36
+ return error;
37
+ }
38
+ return fallback;
39
+ };
40
+ const findOptions = (query, container, args) => {
41
+ const userOptions = extractWaitForOptions(args);
42
+ const onTimeout = userOptions.onTimeout ?? ((fallback) => reRunForDiagnostics(query, container, args, fallback));
43
+ return {
44
+ stackTraceError: new Error("STACK_TRACE_MESSAGE"),
45
+ onTimeout,
46
+ timeout: userOptions.timeout,
47
+ interval: userOptions.interval,
48
+ };
49
+ };
50
+ const singleFrom = (allQuery, getMultipleError) => (container, ...args) => {
51
+ const matches = allQuery(container, ...args);
52
+ if (matches.length > 1)
53
+ throw getMultipleError(container, matches, ...args);
54
+ return matches[0] ?? null;
55
+ };
56
+ const allOrThrow = (allQuery, getMissingError) => (container, ...args) => {
57
+ const matches = allQuery(container, ...args);
58
+ if (matches.length === 0)
59
+ throw getMissingError(container, ...args);
60
+ return matches;
61
+ };
62
+ const wrapSingleWithSuggestion = (query, queryName, variant) => (container, ...args) => {
63
+ const match = query(container, ...args);
64
+ if (match) {
65
+ maybeThrowSuggestion({ container, match, queryName, variant, suggest: extractSuggestOption(args) });
66
+ }
67
+ return match;
68
+ };
69
+ const wrapAllWithSuggestion = (query, queryName, variant) => (container, ...args) => {
70
+ const matches = query(container, ...args);
71
+ const [first] = matches;
72
+ if (first !== undefined) {
73
+ maybeThrowSuggestion({ container, match: first, queryName, variant, suggest: extractSuggestOption(args) });
74
+ }
75
+ return matches;
76
+ };
77
+ const requireSingle = (query, getMissingError) => (container, ...args) => {
78
+ const match = query(container, ...args);
79
+ if (match === null)
80
+ throw getMissingError(container, ...args);
81
+ return match;
82
+ };
83
+ export const buildQueries = (queryName, queryAllBy, getMultipleError, getMissingError) => {
84
+ const getAllBy = allOrThrow(queryAllBy, getMissingError);
85
+ const getBy = requireSingle(singleFrom(getAllBy, getMultipleError), getMissingError);
86
+ const queryByWithSuggestion = wrapSingleWithSuggestion(singleFrom(queryAllBy, getMultipleError), queryName, "query");
87
+ const getAllByWithSuggestion = wrapAllWithSuggestion(getAllBy, queryName, "getAll");
88
+ const getByWithSuggestion = (container, ...args) => {
89
+ const match = getBy(container, ...args);
90
+ maybeThrowSuggestion({ container, match, queryName, variant: "get", suggest: extractSuggestOption(args) });
91
+ return match;
92
+ };
93
+ const findAllBy = (container, ...args) => waitFor(() => runWithExpensiveErrorDiagnosticsDisabled(() => getAllByWithSuggestion(container, ...args)), findOptions(getAllByWithSuggestion, container, args));
94
+ const findBy = (container, ...args) => waitFor(() => runWithExpensiveErrorDiagnosticsDisabled(() => getByWithSuggestion(container, ...args)), findOptions(getByWithSuggestion, container, args));
95
+ return {
96
+ queryBy: queryByWithSuggestion,
97
+ getAllBy: getAllByWithSuggestion,
98
+ getBy: getByWithSuggestion,
99
+ findAllBy,
100
+ findBy,
101
+ };
102
+ };
103
+ //# sourceMappingURL=build-queries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-queries.js","sourceRoot":"","sources":["../src/build-queries.ts"],"names":[],"mappings":"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","sourcesContent":["import type * as Gtk from \"@gtkx/gi/gtk\";\nimport { getConfig } from \"./config.js\";\nimport { runWithExpensiveErrorDiagnosticsDisabled, suggestionError } from \"./errors.js\";\nimport { getSuggestedQuery, type Method, type Variant } from \"./suggestions.js\";\nimport type { Container } from \"./traversal.js\";\nimport type { MatcherOptions, WaitForOptions } from \"./types.js\";\nimport { waitFor } from \"./wait-for.js\";\n\nexport type QueryAllBy<Args extends unknown[]> = (container: Container, ...args: Args) => Gtk.Widget[];\n\ntype MultipleErrorBuilder<Args extends unknown[]> = (\n container: Container,\n matches: Gtk.Widget[],\n ...args: Args\n) => Error;\ntype MissingErrorBuilder<Args extends unknown[]> = (container: Container, ...args: Args) => Error;\n\nexport type BuiltQueries<Args extends unknown[]> = {\n queryBy: (container: Container, ...args: Args) => Gtk.Widget | null;\n getAllBy: QueryAllBy<Args>;\n getBy: (container: Container, ...args: Args) => Gtk.Widget;\n findAllBy: (container: Container, ...args: Args) => Promise<Gtk.Widget[]>;\n findBy: (container: Container, ...args: Args) => Promise<Gtk.Widget>;\n};\n\nconst extractWaitForOptions = (args: unknown[]): WaitForOptions => {\n const last = args[args.length - 1];\n if (last && typeof last === \"object\" && !(last instanceof RegExp)) {\n const { timeout, interval, onTimeout } = last as WaitForOptions;\n return { timeout, interval, onTimeout };\n }\n return {};\n};\n\nconst extractSuggestOption = (args: unknown[]): boolean | undefined => {\n const last = args[args.length - 1];\n if (last && typeof last === \"object\" && !(last instanceof RegExp)) {\n return (last as MatcherOptions).suggest;\n }\n return undefined;\n};\n\nconst maybeThrowSuggestion = (options: {\n container: Container;\n match: Gtk.Widget;\n queryName: Method;\n variant: Variant;\n suggest: boolean | undefined;\n}): void => {\n const { container, match, queryName, variant, suggest } = options;\n const shouldSuggest = suggest ?? getConfig().throwSuggestions;\n if (!shouldSuggest) return;\n\n const suggestion = getSuggestedQuery(match, variant);\n if (suggestion && suggestion.queryName !== queryName) {\n throw suggestionError(suggestion.toString(), container);\n }\n};\n\ntype FindQuery<Args extends unknown[]> = (container: Container, ...args: Args) => unknown;\n\nconst reRunForDiagnostics = <Args extends unknown[]>(\n query: FindQuery<Args>,\n container: Container,\n args: Args,\n fallback: Error,\n): Error => {\n try {\n query(container, ...args);\n } catch (error) {\n if (error instanceof Error) return error;\n }\n return fallback;\n};\n\nconst findOptions = <Args extends unknown[]>(\n query: FindQuery<Args>,\n container: Container,\n args: Args,\n): WaitForOptions => {\n const userOptions = extractWaitForOptions(args);\n const onTimeout =\n userOptions.onTimeout ?? ((fallback: Error) => reRunForDiagnostics(query, container, args, fallback));\n return {\n stackTraceError: new Error(\"STACK_TRACE_MESSAGE\"),\n onTimeout,\n timeout: userOptions.timeout,\n interval: userOptions.interval,\n };\n};\n\ntype SingleQuery<Args extends unknown[]> = (container: Container, ...args: Args) => Gtk.Widget | null;\n\nconst singleFrom =\n <Args extends unknown[]>(\n allQuery: QueryAllBy<Args>,\n getMultipleError: MultipleErrorBuilder<Args>,\n ): SingleQuery<Args> =>\n (container, ...args) => {\n const matches = allQuery(container, ...args);\n if (matches.length > 1) throw getMultipleError(container, matches, ...args);\n return matches[0] ?? null;\n };\n\nconst allOrThrow =\n <Args extends unknown[]>(\n allQuery: QueryAllBy<Args>,\n getMissingError: MissingErrorBuilder<Args>,\n ): QueryAllBy<Args> =>\n (container, ...args) => {\n const matches = allQuery(container, ...args);\n if (matches.length === 0) throw getMissingError(container, ...args);\n return matches;\n };\n\nconst wrapSingleWithSuggestion =\n <Args extends unknown[]>(query: SingleQuery<Args>, queryName: Method, variant: Variant): SingleQuery<Args> =>\n (container, ...args) => {\n const match = query(container, ...args);\n if (match) {\n maybeThrowSuggestion({ container, match, queryName, variant, suggest: extractSuggestOption(args) });\n }\n return match;\n };\n\nconst wrapAllWithSuggestion =\n <Args extends unknown[]>(query: QueryAllBy<Args>, queryName: Method, variant: Variant): QueryAllBy<Args> =>\n (container, ...args) => {\n const matches = query(container, ...args);\n const [first] = matches;\n if (first !== undefined) {\n maybeThrowSuggestion({ container, match: first, queryName, variant, suggest: extractSuggestOption(args) });\n }\n return matches;\n };\n\nconst requireSingle =\n <Args extends unknown[]>(query: SingleQuery<Args>, getMissingError: MissingErrorBuilder<Args>) =>\n (container: Container, ...args: Args): Gtk.Widget => {\n const match = query(container, ...args);\n if (match === null) throw getMissingError(container, ...args);\n return match;\n };\n\nexport const buildQueries = <Args extends unknown[]>(\n queryName: Method,\n queryAllBy: QueryAllBy<Args>,\n getMultipleError: MultipleErrorBuilder<Args>,\n getMissingError: MissingErrorBuilder<Args>,\n): BuiltQueries<Args> => {\n const getAllBy = allOrThrow(queryAllBy, getMissingError);\n const getBy = requireSingle(singleFrom(getAllBy, getMultipleError), getMissingError);\n\n const queryByWithSuggestion = wrapSingleWithSuggestion(\n singleFrom(queryAllBy, getMultipleError),\n queryName,\n \"query\",\n );\n const getAllByWithSuggestion = wrapAllWithSuggestion(getAllBy, queryName, \"getAll\");\n const getByWithSuggestion: (container: Container, ...args: Args) => Gtk.Widget = (container, ...args) => {\n const match = getBy(container, ...args);\n maybeThrowSuggestion({ container, match, queryName, variant: \"get\", suggest: extractSuggestOption(args) });\n return match;\n };\n\n const findAllBy = (container: Container, ...args: Args): Promise<Gtk.Widget[]> =>\n waitFor(\n () => runWithExpensiveErrorDiagnosticsDisabled(() => getAllByWithSuggestion(container, ...args)),\n findOptions(getAllByWithSuggestion, container, args),\n );\n\n const findBy = (container: Container, ...args: Args): Promise<Gtk.Widget> =>\n waitFor(\n () => runWithExpensiveErrorDiagnosticsDisabled(() => getByWithSuggestion(container, ...args)),\n findOptions(getByWithSuggestion, container, args),\n );\n\n return {\n queryBy: queryByWithSuggestion,\n getAllBy: getAllByWithSuggestion,\n getBy: getByWithSuggestion,\n findAllBy,\n findBy,\n };\n};\n"]}
@@ -0,0 +1,4 @@
1
+ export type CleanupFunction = () => void | Promise<void>;
2
+ export declare const addToCleanupQueue: (fn: CleanupFunction) => void;
3
+ export declare const runCleanup: () => Promise<void>;
4
+ //# sourceMappingURL=cleanup-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cleanup-registry.d.ts","sourceRoot":"","sources":["../src/cleanup-registry.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAIzD,eAAO,MAAM,iBAAiB,OAAQ,eAAe,KAAG,IAEvD,CAAC;AAEF,eAAO,MAAM,UAAU,QAAa,OAAO,CAAC,IAAI,CAK/C,CAAC"}
@@ -0,0 +1,11 @@
1
+ const cleanupQueue = new Set();
2
+ export const addToCleanupQueue = (fn) => {
3
+ cleanupQueue.add(fn);
4
+ };
5
+ export const runCleanup = async () => {
6
+ for (const fn of cleanupQueue) {
7
+ await fn();
8
+ }
9
+ cleanupQueue.clear();
10
+ };
11
+ //# sourceMappingURL=cleanup-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cleanup-registry.js","sourceRoot":"","sources":["../src/cleanup-registry.ts"],"names":[],"mappings":"AAEA,MAAM,YAAY,GAAG,IAAI,GAAG,EAAmB,CAAC;AAEhD,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,EAAmB,EAAQ,EAAE;IAC3D,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AACzB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,IAAmB,EAAE;IAChD,KAAK,MAAM,EAAE,IAAI,YAAY,EAAE,CAAC;QAC5B,MAAM,EAAE,EAAE,CAAC;IACf,CAAC;IACD,YAAY,CAAC,KAAK,EAAE,CAAC;AACzB,CAAC,CAAC","sourcesContent":["export type CleanupFunction = () => void | Promise<void>;\n\nconst cleanupQueue = new Set<CleanupFunction>();\n\nexport const addToCleanupQueue = (fn: CleanupFunction): void => {\n cleanupQueue.add(fn);\n};\n\nexport const runCleanup = async (): Promise<void> => {\n for (const fn of cleanupQueue) {\n await fn();\n }\n cleanupQueue.clear();\n};\n"]}
package/dist/config.d.ts CHANGED
@@ -1,65 +1,32 @@
1
1
  import type { Container } from "./traversal.js";
2
2
  /**
3
- * Configuration options for the testing library.
3
+ * Global configuration for the testing harness, controlling query behavior,
4
+ * error formatting, and the timeouts used by async utilities and actionability
5
+ * checks.
4
6
  */
5
7
  export type Config = {
6
- /**
7
- * Whether to show role suggestions in error messages when elements are not found.
8
- * @default true
9
- */
10
- showSuggestions: boolean;
11
- /**
12
- * Custom error factory for query failures.
13
- * Allows customizing how errors are constructed.
14
- */
15
- getElementError: (message: string, container: Container) => Error;
16
- /**
17
- * Default timeout in milliseconds for async utilities (waitFor, findBy* queries).
18
- * @default 1000
19
- */
8
+ throwSuggestions: boolean;
9
+ /** Builds the error thrown when a query fails, given a message and optional container. */
10
+ getElementError: (message: string, container?: Container) => Error;
11
+ /** Default timeout in milliseconds for async utilities such as waitFor. */
20
12
  asyncUtilTimeout: number;
13
+ /** Timeout in milliseconds for waiting on a widget to become actionable. */
14
+ actionabilityTimeout: number;
21
15
  };
22
16
  /**
23
- * Returns the current testing library configuration.
24
- *
25
- * @returns The current configuration object
26
- *
27
- * @example
28
- * ```tsx
29
- * import { getConfig } from "@gtkx/testing";
30
- *
31
- * const config = getConfig();
32
- * console.log(config.showSuggestions);
33
- * ```
17
+ * Function form of a configuration update: receives the current config and
18
+ * returns the fields to override.
34
19
  */
35
- export declare const getConfig: () => Readonly<Config>;
20
+ export type ConfigFn = (existingConfig: Config) => Partial<Config>;
36
21
  /**
37
- * Configures the testing library behavior.
38
- *
39
- * Accepts either a partial configuration object or a function that receives
40
- * the current configuration and returns updates.
41
- *
42
- * @param newConfig - Partial configuration or updater function
43
- *
44
- * @example
45
- * ```tsx
46
- * import { configure } from "@gtkx/testing";
47
- *
48
- * // Disable role suggestions
49
- * configure({ showSuggestions: false });
50
- *
51
- * // Use updater function
52
- * configure((current) => ({
53
- * showSuggestions: !current.showSuggestions,
54
- * }));
55
- * ```
22
+ * Returns the current global testing configuration.
56
23
  */
57
- export declare const configure: (newConfig: Partial<Config> | ((current: Config) => Partial<Config>)) => void;
24
+ export declare const getConfig: () => Config;
58
25
  /**
59
- * Resets configuration to defaults.
60
- * Primarily used for testing.
26
+ * Merges the given overrides into the global testing configuration.
61
27
  *
62
- * @internal
28
+ * @param newConfig Either a partial config object or a function that receives
29
+ * the current config and returns the fields to override.
63
30
  */
64
- export declare const resetConfig: () => void;
31
+ export declare const configure: (newConfig: Partial<Config> | ConfigFn) => void;
65
32
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD;;GAEG;AACH,MAAM,MAAM,MAAM,GAAG;IACjB;;;OAGG;IACH,eAAe,EAAE,OAAO,CAAC;IAEzB;;;OAGG;IACH,eAAe,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,KAAK,KAAK,CAAC;IAElE;;;OAGG;IACH,gBAAgB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAcF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,SAAS,QAAO,QAAQ,CAAC,MAAM,CAE3C,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,SAAS,GAAI,WAAW,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC,KAAG,IAG/F,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,WAAW,QAAO,IAE9B,CAAC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD;;;;GAIG;AACH,MAAM,MAAM,MAAM,GAAG;IACjB,gBAAgB,EAAE,OAAO,CAAC;IAE1B,0FAA0F;IAC1F,eAAe,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,SAAS,KAAK,KAAK,CAAC;IAEnE,2EAA2E;IAC3E,gBAAgB,EAAE,MAAM,CAAC;IAEzB,4EAA4E;IAC5E,oBAAoB,EAAE,MAAM,CAAC;CAChC,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,cAAc,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAiBnE;;GAEG;AACH,eAAO,MAAM,SAAS,QAAO,MAE5B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,SAAS,cAAe,OAAO,CAAC,MAAM,CAAC,GAAG,QAAQ,KAAG,IAGjE,CAAC"}