@gtkx/testing 1.6.0 → 2.0.0-beta.2
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 +5 -5
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -3
- package/dist/config.js.map +1 -1
- package/dist/fire-event.js +1 -1
- package/dist/fire-event.js.map +1 -1
- package/dist/matchers.d.ts.map +1 -1
- package/dist/matchers.js +1 -14
- package/dist/matchers.js.map +1 -1
- package/dist/queries.d.ts +30 -126
- package/dist/queries.d.ts.map +1 -1
- package/dist/queries.js +30 -126
- package/dist/queries.js.map +1 -1
- package/dist/query-helpers.d.ts.map +1 -1
- package/dist/query-helpers.js +8 -2
- package/dist/query-helpers.js.map +1 -1
- package/dist/screenshot.d.ts.map +1 -1
- package/dist/screenshot.js +1 -3
- package/dist/screenshot.js.map +1 -1
- package/dist/user-event/adjustment.d.ts +2 -14
- package/dist/user-event/adjustment.d.ts.map +1 -1
- package/dist/user-event/adjustment.js +2 -14
- package/dist/user-event/adjustment.js.map +1 -1
- package/dist/user-event/click.d.ts +3 -41
- package/dist/user-event/click.d.ts.map +1 -1
- package/dist/user-event/click.js +5 -43
- package/dist/user-event/click.js.map +1 -1
- package/dist/user-event/gesture.d.ts +9 -43
- package/dist/user-event/gesture.d.ts.map +1 -1
- package/dist/user-event/gesture.js +9 -43
- package/dist/user-event/gesture.js.map +1 -1
- package/dist/user-event/index.d.ts +16 -85
- package/dist/user-event/index.d.ts.map +1 -1
- package/dist/user-event/index.js +1 -5
- package/dist/user-event/index.js.map +1 -1
- package/dist/user-event/keyboard.d.ts +1 -1
- package/dist/user-event/keyboard.d.ts.map +1 -1
- package/dist/user-event/keyboard.js +1 -1
- package/dist/user-event/keyboard.js.map +1 -1
- package/dist/user-event/list-row-click.d.ts +1 -1
- package/dist/user-event/list-row-click.d.ts.map +1 -1
- package/dist/user-event/list-row-click.js +2 -1
- package/dist/user-event/list-row-click.js.map +1 -1
- package/dist/user-event/selection.d.ts +2 -18
- package/dist/user-event/selection.d.ts.map +1 -1
- package/dist/user-event/selection.js +3 -21
- package/dist/user-event/selection.js.map +1 -1
- package/dist/user-event/text.d.ts +5 -34
- package/dist/user-event/text.d.ts.map +1 -1
- package/dist/user-event/text.js +5 -34
- package/dist/user-event/text.js.map +1 -1
- package/dist/widget-accessible-properties.d.ts.map +1 -1
- package/dist/widget-accessible-properties.js +14 -34
- package/dist/widget-accessible-properties.js.map +1 -1
- package/package.json +12 -8
- package/src/config.ts +1 -3
- package/src/fire-event.ts +1 -1
- package/src/matchers.ts +1 -22
- package/src/queries.ts +30 -126
- package/src/query-helpers.ts +8 -2
- package/src/screenshot.ts +1 -3
- package/src/user-event/adjustment.ts +2 -14
- package/src/user-event/click.ts +5 -43
- package/src/user-event/gesture.ts +9 -43
- package/src/user-event/index.ts +16 -85
- package/src/user-event/keyboard.ts +1 -1
- package/src/user-event/list-row-click.ts +2 -2
- package/src/user-event/selection.ts +3 -21
- package/src/user-event/text.ts +5 -34
- package/src/widget-accessible-properties.ts +22 -44
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gtkx/testing",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-beta.2",
|
|
4
4
|
"description": "Queries, events, and screenshots for GTK and GTK4 widget trees.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"gtkx",
|
|
@@ -29,10 +29,14 @@
|
|
|
29
29
|
"./package.json": "./package.json",
|
|
30
30
|
".": {
|
|
31
31
|
"types": "./dist/index.d.ts",
|
|
32
|
+
"import": "./dist/index.js",
|
|
33
|
+
"require": null,
|
|
32
34
|
"default": "./dist/index.js"
|
|
33
35
|
},
|
|
34
36
|
"./internal": {
|
|
35
37
|
"types": "./dist/internal.d.ts",
|
|
38
|
+
"import": "./dist/internal.js",
|
|
39
|
+
"require": null,
|
|
36
40
|
"default": "./dist/internal.js"
|
|
37
41
|
}
|
|
38
42
|
},
|
|
@@ -55,22 +59,22 @@
|
|
|
55
59
|
}
|
|
56
60
|
},
|
|
57
61
|
"engines": {
|
|
58
|
-
"node": ">=
|
|
62
|
+
"node": ">=26.7.0"
|
|
59
63
|
},
|
|
60
64
|
"dependencies": {
|
|
65
|
+
"@gtkx/runtime": "2.0.0-beta.2",
|
|
66
|
+
"@gtkx/react": "2.0.0-beta.2",
|
|
67
|
+
"@gtkx/utils": "2.0.0-beta.2",
|
|
61
68
|
"@vitest/expect": "^4.1.11",
|
|
62
|
-
"@vitest/pretty-format": "^4.1.11"
|
|
63
|
-
"@gtkx/react": "1.6.0",
|
|
64
|
-
"@gtkx/utils": "1.6.0",
|
|
65
|
-
"@gtkx/runtime": "1.6.0"
|
|
69
|
+
"@vitest/pretty-format": "^4.1.11"
|
|
66
70
|
},
|
|
67
71
|
"peerDependencies": {
|
|
68
72
|
"@types/react": "^19.2",
|
|
69
73
|
"react": "^19.2"
|
|
70
74
|
},
|
|
71
75
|
"devDependencies": {
|
|
72
|
-
"@
|
|
73
|
-
"@
|
|
76
|
+
"@gtkx/config": "2.0.0-beta.2",
|
|
77
|
+
"@types/react": "^19.2.18"
|
|
74
78
|
},
|
|
75
79
|
"scripts": {
|
|
76
80
|
"release": "tsx ../../scripts/release-package.ts"
|
package/src/config.ts
CHANGED
|
@@ -50,9 +50,7 @@ function defaultGetElementError(message: string): Error {
|
|
|
50
50
|
/**
|
|
51
51
|
* Returns the current global testing configuration.
|
|
52
52
|
*/
|
|
53
|
-
const getConfig = (): Config =>
|
|
54
|
-
return currentConfig;
|
|
55
|
-
};
|
|
53
|
+
const getConfig = (): Config => currentConfig;
|
|
56
54
|
|
|
57
55
|
/**
|
|
58
56
|
* Merges the given overrides into the global testing configuration.
|
package/src/fire-event.ts
CHANGED
|
@@ -31,7 +31,7 @@ const createEvent = (target: GObject.Object, signalName: string, ...args: unknow
|
|
|
31
31
|
|
|
32
32
|
const dispatchEvent = async (event: WidgetEvent): Promise<void> => {
|
|
33
33
|
await runInAct(() => {
|
|
34
|
-
event.target
|
|
34
|
+
Reflect.apply(GObject.signalEmit, undefined, [event.target, event.signalName, ...event.args]);
|
|
35
35
|
});
|
|
36
36
|
};
|
|
37
37
|
|
package/src/matchers.ts
CHANGED
|
@@ -525,9 +525,6 @@ const isAppearingBefore = (first: Gtk.Widget, second: Gtk.Widget): boolean => {
|
|
|
525
525
|
return isSeparateWidget(first, second) && root === getTreeRoot(second) && isPrecedingWidget(root, first, second);
|
|
526
526
|
};
|
|
527
527
|
|
|
528
|
-
const camelCase = (name: string): string =>
|
|
529
|
-
name.replaceAll(/-([a-z])/g, (_match, letter: string) => letter.toUpperCase());
|
|
530
|
-
|
|
531
528
|
const isAsymmetricMatcher = (value: unknown): boolean =>
|
|
532
529
|
typeof value === "object" && value !== null && typeof Reflect.get(value, "asymmetricMatch") === "function";
|
|
533
530
|
|
|
@@ -588,26 +585,8 @@ function readErrorMessageText(widget: Gtk.Widget): string | null {
|
|
|
588
585
|
return texts.length > 0 ? texts.join(" ") : null;
|
|
589
586
|
}
|
|
590
587
|
|
|
591
|
-
function assertReadableProperty(object: GObject.Object, name: string, property: string, value: unknown): void {
|
|
592
|
-
if (typeof value === "function") {
|
|
593
|
-
throw new TypeError(
|
|
594
|
-
`toHaveObjectProperty: "${name}" is shadowed by a method of the same name; ` +
|
|
595
|
-
`call ${property}() and assert on its result instead`,
|
|
596
|
-
);
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
if (value === undefined && !Reflect.has(object, property)) {
|
|
600
|
-
throw new TypeError(
|
|
601
|
-
`toHaveObjectProperty: no readable property "${name}" on ${describeObject(object)}; ` +
|
|
602
|
-
"construct-only and write-only properties cannot be read back",
|
|
603
|
-
);
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
|
|
607
588
|
function readObjectProperty(object: GObject.Object, name: string): unknown {
|
|
608
|
-
const
|
|
609
|
-
const value: unknown = Reflect.get(object, property);
|
|
610
|
-
assertReadableProperty(object, name, property, value);
|
|
589
|
+
const value: unknown = Reflect.apply(GObject.getObjectProperty, undefined, [object, name]);
|
|
611
590
|
|
|
612
591
|
return value;
|
|
613
592
|
}
|
package/src/queries.ts
CHANGED
|
@@ -106,161 +106,65 @@ const builtinQueries = {
|
|
|
106
106
|
...displayValueQueries,
|
|
107
107
|
} as BuiltinQueries;
|
|
108
108
|
|
|
109
|
-
/**
|
|
110
|
-
* Returns the single mapped widget with a matching accessible role and options, or null when none
|
|
111
|
-
* match. Widgets that are not mapped are never matched. Throws when more than one matches.
|
|
112
|
-
*/
|
|
109
|
+
/** Queries one mapped widget by accessible role. */
|
|
113
110
|
const queryByRole: BuiltinQueries["queryByRole"] = builtinQueries.queryByRole;
|
|
114
|
-
/**
|
|
115
|
-
* Returns every mapped widget with a matching accessible role and options. Widgets that are not
|
|
116
|
-
* mapped are never matched. Throws when none match.
|
|
117
|
-
*/
|
|
111
|
+
/** Gets all mapped widgets with an accessible role. */
|
|
118
112
|
const getAllByRole: BuiltinQueries["getAllByRole"] = builtinQueries.getAllByRole;
|
|
119
|
-
/**
|
|
120
|
-
* Returns the single mapped widget with a matching accessible role and options. Widgets that are not
|
|
121
|
-
* mapped are never matched. Throws when none or more than one matches.
|
|
122
|
-
*/
|
|
113
|
+
/** Gets one mapped widget by accessible role. */
|
|
123
114
|
const getByRole: BuiltinQueries["getByRole"] = builtinQueries.getByRole;
|
|
124
|
-
/**
|
|
125
|
-
* Waits for and returns every mapped widget with a matching accessible role and options, retrying
|
|
126
|
-
* until at least one appears or the timeout elapses. Widgets that are not mapped are never matched.
|
|
127
|
-
*/
|
|
115
|
+
/** Finds all mapped widgets with an accessible role. */
|
|
128
116
|
const findAllByRole: BuiltinQueries["findAllByRole"] = builtinQueries.findAllByRole;
|
|
129
|
-
/**
|
|
130
|
-
* Waits for and returns the single mapped widget with a matching accessible role and options,
|
|
131
|
-
* retrying until it appears or the timeout elapses. Widgets that are not mapped are never matched.
|
|
132
|
-
* Rejects when none or more than one matches.
|
|
133
|
-
*/
|
|
117
|
+
/** Finds one mapped widget by accessible role. */
|
|
134
118
|
const findByRole: BuiltinQueries["findByRole"] = builtinQueries.findByRole;
|
|
135
|
-
/**
|
|
136
|
-
* Returns the single mapped widget with matching associated label text, or null when none match.
|
|
137
|
-
* Widgets that are not mapped are never matched. Throws when more than one matches.
|
|
138
|
-
*/
|
|
119
|
+
/** Queries one mapped widget by label text. */
|
|
139
120
|
const queryByLabelText: BuiltinQueries["queryByLabelText"] = builtinQueries.queryByLabelText;
|
|
140
|
-
/**
|
|
141
|
-
* Returns every mapped widget with matching associated label text. Widgets that are not mapped are
|
|
142
|
-
* never matched. Throws when none match.
|
|
143
|
-
*/
|
|
121
|
+
/** Gets all mapped widgets with label text. */
|
|
144
122
|
const getAllByLabelText: BuiltinQueries["getAllByLabelText"] = builtinQueries.getAllByLabelText;
|
|
145
|
-
/**
|
|
146
|
-
* Returns the single mapped widget with matching associated label text. Widgets that are not mapped
|
|
147
|
-
* are never matched. Throws when none or more than one matches.
|
|
148
|
-
*/
|
|
123
|
+
/** Gets one mapped widget by label text. */
|
|
149
124
|
const getByLabelText: BuiltinQueries["getByLabelText"] = builtinQueries.getByLabelText;
|
|
150
|
-
/**
|
|
151
|
-
* Waits for and returns every mapped widget with matching associated label text, retrying until at
|
|
152
|
-
* least one appears or the timeout elapses. Widgets that are not mapped are never matched.
|
|
153
|
-
*/
|
|
125
|
+
/** Finds all mapped widgets with label text. */
|
|
154
126
|
const findAllByLabelText: BuiltinQueries["findAllByLabelText"] = builtinQueries.findAllByLabelText;
|
|
155
|
-
/**
|
|
156
|
-
* Waits for and returns the single mapped widget with matching associated label text, retrying until
|
|
157
|
-
* it appears or the timeout elapses. Widgets that are not mapped are never matched. Rejects when
|
|
158
|
-
* none or more than one matches.
|
|
159
|
-
*/
|
|
127
|
+
/** Finds one mapped widget by label text. */
|
|
160
128
|
const findByLabelText: BuiltinQueries["findByLabelText"] = builtinQueries.findByLabelText;
|
|
161
|
-
/**
|
|
162
|
-
* Returns the single mapped widget with matching rendered text content, or null when none match.
|
|
163
|
-
* Widgets that are not mapped are never matched. Throws when more than one matches.
|
|
164
|
-
*/
|
|
129
|
+
/** Queries one mapped widget by rendered text. */
|
|
165
130
|
const queryByText: BuiltinQueries["queryByText"] = builtinQueries.queryByText;
|
|
166
|
-
/**
|
|
167
|
-
* Returns every mapped widget with matching rendered text content. Widgets that are not mapped are
|
|
168
|
-
* never matched. Throws when none match.
|
|
169
|
-
*/
|
|
131
|
+
/** Gets all mapped widgets with rendered text. */
|
|
170
132
|
const getAllByText: BuiltinQueries["getAllByText"] = builtinQueries.getAllByText;
|
|
171
|
-
/**
|
|
172
|
-
* Returns the single mapped widget with matching rendered text content. Widgets that are not mapped
|
|
173
|
-
* are never matched. Throws when none or more than one matches.
|
|
174
|
-
*/
|
|
133
|
+
/** Gets one mapped widget by rendered text. */
|
|
175
134
|
const getByText: BuiltinQueries["getByText"] = builtinQueries.getByText;
|
|
176
|
-
/**
|
|
177
|
-
* Waits for and returns every mapped widget with matching rendered text content, retrying until at
|
|
178
|
-
* least one appears or the timeout elapses. Widgets that are not mapped are never matched.
|
|
179
|
-
*/
|
|
135
|
+
/** Finds all mapped widgets with rendered text. */
|
|
180
136
|
const findAllByText: BuiltinQueries["findAllByText"] = builtinQueries.findAllByText;
|
|
181
|
-
/**
|
|
182
|
-
* Waits for and returns the single mapped widget with matching rendered text content, retrying until
|
|
183
|
-
* it appears or the timeout elapses. Widgets that are not mapped are never matched. Rejects when
|
|
184
|
-
* none or more than one matches.
|
|
185
|
-
*/
|
|
137
|
+
/** Finds one mapped widget by rendered text. */
|
|
186
138
|
const findByText: BuiltinQueries["findByText"] = builtinQueries.findByText;
|
|
187
|
-
/**
|
|
188
|
-
* Returns the single mapped widget with a matching widget name, or null when none match. Widgets
|
|
189
|
-
* that are not mapped are never matched. Throws when more than one matches.
|
|
190
|
-
*/
|
|
139
|
+
/** Queries one mapped widget by GTK name. */
|
|
191
140
|
const queryByName: BuiltinQueries["queryByName"] = builtinQueries.queryByName;
|
|
192
|
-
/**
|
|
193
|
-
* Returns every mapped widget with a matching widget name. Widgets that are not mapped are never
|
|
194
|
-
* matched. Throws when none match.
|
|
195
|
-
*/
|
|
141
|
+
/** Gets all mapped widgets with a GTK name. */
|
|
196
142
|
const getAllByName: BuiltinQueries["getAllByName"] = builtinQueries.getAllByName;
|
|
197
|
-
/**
|
|
198
|
-
* Returns the single mapped widget with a matching widget name. Widgets that are not mapped are
|
|
199
|
-
* never matched. Throws when none or more than one matches.
|
|
200
|
-
*/
|
|
143
|
+
/** Gets one mapped widget by GTK name. */
|
|
201
144
|
const getByName: BuiltinQueries["getByName"] = builtinQueries.getByName;
|
|
202
|
-
/**
|
|
203
|
-
* Waits for and returns every mapped widget with a matching widget name, retrying until at least one
|
|
204
|
-
* appears or the timeout elapses. Widgets that are not mapped are never matched.
|
|
205
|
-
*/
|
|
145
|
+
/** Finds all mapped widgets with a GTK name. */
|
|
206
146
|
const findAllByName: BuiltinQueries["findAllByName"] = builtinQueries.findAllByName;
|
|
207
|
-
/**
|
|
208
|
-
* Waits for and returns the single mapped widget with a matching widget name, retrying until it
|
|
209
|
-
* appears or the timeout elapses. Widgets that are not mapped are never matched. Rejects when none
|
|
210
|
-
* or more than one matches.
|
|
211
|
-
*/
|
|
147
|
+
/** Finds one mapped widget by GTK name. */
|
|
212
148
|
const findByName: BuiltinQueries["findByName"] = builtinQueries.findByName;
|
|
213
|
-
/**
|
|
214
|
-
* Returns the single mapped widget with matching placeholder text, or null when none match. Widgets
|
|
215
|
-
* that are not mapped are never matched. Throws when more than one matches.
|
|
216
|
-
*/
|
|
149
|
+
/** Queries one mapped widget by placeholder text. */
|
|
217
150
|
const queryByPlaceholderText: BuiltinQueries["queryByPlaceholderText"] = builtinQueries.queryByPlaceholderText;
|
|
218
|
-
/**
|
|
219
|
-
* Returns every mapped widget with matching placeholder text. Widgets that are not mapped are never
|
|
220
|
-
* matched. Throws when none match.
|
|
221
|
-
*/
|
|
151
|
+
/** Gets all mapped widgets with placeholder text. */
|
|
222
152
|
const getAllByPlaceholderText: BuiltinQueries["getAllByPlaceholderText"] = builtinQueries.getAllByPlaceholderText;
|
|
223
|
-
/**
|
|
224
|
-
* Returns the single mapped widget with matching placeholder text. Widgets that are not mapped are
|
|
225
|
-
* never matched. Throws when none or more than one matches.
|
|
226
|
-
*/
|
|
153
|
+
/** Gets one mapped widget by placeholder text. */
|
|
227
154
|
const getByPlaceholderText: BuiltinQueries["getByPlaceholderText"] = builtinQueries.getByPlaceholderText;
|
|
228
|
-
/**
|
|
229
|
-
* Waits for and returns every mapped widget with matching placeholder text, retrying until at least
|
|
230
|
-
* one appears or the timeout elapses. Widgets that are not mapped are never matched.
|
|
231
|
-
*/
|
|
155
|
+
/** Finds all mapped widgets with placeholder text. */
|
|
232
156
|
const findAllByPlaceholderText: BuiltinQueries["findAllByPlaceholderText"] = builtinQueries.findAllByPlaceholderText;
|
|
233
|
-
/**
|
|
234
|
-
* Waits for and returns the single mapped widget with matching placeholder text, retrying until it
|
|
235
|
-
* appears or the timeout elapses. Widgets that are not mapped are never matched. Rejects when none
|
|
236
|
-
* or more than one matches.
|
|
237
|
-
*/
|
|
157
|
+
/** Finds one mapped widget by placeholder text. */
|
|
238
158
|
const findByPlaceholderText: BuiltinQueries["findByPlaceholderText"] = builtinQueries.findByPlaceholderText;
|
|
239
|
-
/**
|
|
240
|
-
* Returns the single mapped widget with a matching display value, or null when none match. Widgets
|
|
241
|
-
* that are not mapped are never matched. Throws when more than one matches.
|
|
242
|
-
*/
|
|
159
|
+
/** Queries one mapped widget by display value. */
|
|
243
160
|
const queryByDisplayValue: BuiltinQueries["queryByDisplayValue"] = builtinQueries.queryByDisplayValue;
|
|
244
|
-
/**
|
|
245
|
-
* Returns every mapped widget with a matching display value. Widgets that are not mapped are never
|
|
246
|
-
* matched. Throws when none match.
|
|
247
|
-
*/
|
|
161
|
+
/** Gets all mapped widgets with a display value. */
|
|
248
162
|
const getAllByDisplayValue: BuiltinQueries["getAllByDisplayValue"] = builtinQueries.getAllByDisplayValue;
|
|
249
|
-
/**
|
|
250
|
-
* Returns the single mapped widget with a matching display value. Widgets that are not mapped are
|
|
251
|
-
* never matched. Throws when none or more than one matches.
|
|
252
|
-
*/
|
|
163
|
+
/** Gets one mapped widget by display value. */
|
|
253
164
|
const getByDisplayValue: BuiltinQueries["getByDisplayValue"] = builtinQueries.getByDisplayValue;
|
|
254
|
-
/**
|
|
255
|
-
* Waits for and returns every mapped widget with a matching display value, retrying until at least
|
|
256
|
-
* one appears or the timeout elapses. Widgets that are not mapped are never matched.
|
|
257
|
-
*/
|
|
165
|
+
/** Finds all mapped widgets with a display value. */
|
|
258
166
|
const findAllByDisplayValue: BuiltinQueries["findAllByDisplayValue"] = builtinQueries.findAllByDisplayValue;
|
|
259
|
-
/**
|
|
260
|
-
* Waits for and returns the single mapped widget with a matching display value, retrying until it
|
|
261
|
-
* appears or the timeout elapses. Widgets that are not mapped are never matched. Rejects when none
|
|
262
|
-
* or more than one matches.
|
|
263
|
-
*/
|
|
167
|
+
/** Finds one mapped widget by display value. */
|
|
264
168
|
const findByDisplayValue: BuiltinQueries["findByDisplayValue"] = builtinQueries.findByDisplayValue;
|
|
265
169
|
|
|
266
170
|
const buildNormalizer = (options?: MatcherOptions): NormalizerFn => {
|
package/src/query-helpers.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type * as Gtk from "@gtkx/gi/gtk";
|
|
2
|
-
import {
|
|
2
|
+
import { getObjectProperty } from "@gtkx/gi/gobject";
|
|
3
3
|
import type { Matcher, MatcherOptions } from "./types.js";
|
|
4
4
|
import { buildQueries } from "./build-queries.js";
|
|
5
5
|
import { getElementError } from "./errors.js";
|
|
@@ -27,7 +27,13 @@ const queryHelpers: QueryHelpers = {
|
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
const readObjectProperty = (widget: Gtk.Widget, property: string): string | null => {
|
|
30
|
-
|
|
30
|
+
let value: unknown;
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
value = Reflect.apply(getObjectProperty, undefined, [widget, property]);
|
|
34
|
+
} catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
31
37
|
|
|
32
38
|
if (typeof value === "string") {
|
|
33
39
|
return value;
|
package/src/screenshot.ts
CHANGED
|
@@ -47,9 +47,7 @@ const OTHER_FAILURE_HINT =
|
|
|
47
47
|
|
|
48
48
|
const NOTHING_ON_SCREEN_MESSAGE = "Nothing is on screen to capture: no toplevel window is mapped";
|
|
49
49
|
|
|
50
|
-
const bytesToBase64 = (bytes: Uint8Array | number[]): string =>
|
|
51
|
-
return Buffer.from(bytes).toString("base64");
|
|
52
|
-
};
|
|
50
|
+
const bytesToBase64 = (bytes: Uint8Array | number[]): string => Buffer.from(bytes).toString("base64");
|
|
53
51
|
|
|
54
52
|
const describeWidgetState = (widget: Gtk.Widget): string =>
|
|
55
53
|
`realized=${String(widget.getRealized())} mapped=${String(widget.getMapped())} ` +
|
|
@@ -16,11 +16,7 @@ type ScrollAdjustments = {
|
|
|
16
16
|
vertical: Gtk.Adjustment | null;
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
/**
|
|
20
|
-
* Emits a jump `change-value` so a Gtk.Range moves to the given value.
|
|
21
|
-
*
|
|
22
|
-
* @throws When the widget is not a Gtk.Range.
|
|
23
|
-
*/
|
|
19
|
+
/** Moves a range to a value. */
|
|
24
20
|
const slide = (widget: Gtk.Widget, value: number): Promise<void> =>
|
|
25
21
|
wrapEvent(widget, () => {
|
|
26
22
|
if (!(widget instanceof Gtk.Range)) {
|
|
@@ -76,15 +72,7 @@ const applyScrollDelta = (adjustment: Gtk.Adjustment | null, delta: number): voi
|
|
|
76
72
|
rampTo(adjustment, adjustment.getValue() + delta, pageSize > 0 ? pageSize : Math.abs(delta));
|
|
77
73
|
};
|
|
78
74
|
|
|
79
|
-
/**
|
|
80
|
-
* Adds the delta to the adjustments of the widget itself, or of its nearest Gtk.ScrolledWindow or
|
|
81
|
-
* Gtk.Scrollable ancestor.
|
|
82
|
-
*
|
|
83
|
-
* Each adjustment advances in viewport-sized steps rather than one jump, so virtualized views such
|
|
84
|
-
* as Gtk.ListView, Gtk.GridView and Gtk.ColumnView re-anchor onto the rows the new offset shows.
|
|
85
|
-
*
|
|
86
|
-
* @throws When neither the widget nor any of its ancestors is scrollable.
|
|
87
|
-
*/
|
|
75
|
+
/** Scrolls the widget or its nearest scrollable ancestor. */
|
|
88
76
|
const scroll = (widget: Gtk.Widget, delta: ScrollDelta): Promise<void> =>
|
|
89
77
|
wrapEvent(widget, async () => {
|
|
90
78
|
const adjustments = resolveScrollAdjustments(widget);
|
package/src/user-event/click.ts
CHANGED
|
@@ -205,7 +205,7 @@ const applyContainerOutcome = (target: ClickTarget, nPress: number): void => {
|
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
if (isActivatedByClick(container, nPress)) {
|
|
208
|
-
|
|
208
|
+
Gtk.Widget.prototype.activate.call(widget);
|
|
209
209
|
}
|
|
210
210
|
|
|
211
211
|
if (isSelectionReplacedByClick(container, nPress)) {
|
|
@@ -246,39 +246,13 @@ const tryActivate = async (widget: Gtk.Widget): Promise<boolean> => {
|
|
|
246
246
|
let isActivated = false;
|
|
247
247
|
|
|
248
248
|
await wrapEvent(widget, () => {
|
|
249
|
-
isActivated =
|
|
249
|
+
isActivated = Gtk.Widget.prototype.activate.call(widget);
|
|
250
250
|
});
|
|
251
251
|
|
|
252
252
|
return isActivated;
|
|
253
253
|
};
|
|
254
254
|
|
|
255
|
-
/**
|
|
256
|
-
* Activates a widget that neither claims the click nor carries a click gesture of its own, and
|
|
257
|
-
* otherwise delivers a press and release. The press travels outwards from the clicked widget
|
|
258
|
-
* through every widget carrying a click gesture with a pressed or released handler, the way GTK
|
|
259
|
-
* hands the same press to each of them, and stops at the first Gtk.Button or indexed child of a
|
|
260
|
-
* list box or flow box, which claims it. A gesture GTK attached itself takes the press only when no
|
|
261
|
-
* widget below it handles one, and stops it there, so an expander or a notebook tab nested in a row
|
|
262
|
-
* opens instead of activating the row. Coordinates are the clicked widget's position in each
|
|
263
|
-
* carrier, so a gesture the container of an indexed child carries reads the child's position rather
|
|
264
|
-
* than the container's center. An indexed child that the press reaches is then activated, or
|
|
265
|
-
* exclusively selected when its container does not activate on a single click. A widget with the
|
|
266
|
-
* label role is never activated, but does consume the click when it carries a gesture of its own.
|
|
267
|
-
*
|
|
268
|
-
* The press also stops at a widget whose click GTK4 implements in C on a gesture it attached
|
|
269
|
-
* itself, reading a GdkEvent that off-screen synthesis cannot produce. Gestures that widget carries
|
|
270
|
-
* of its own still take the press and release, the way GTK hands them the press before its own
|
|
271
|
-
* gesture claims it, and the same outcome is then applied through the public action GTK's own
|
|
272
|
-
* handler invokes: a list, grid, or column-view row is focused and selected, and activated as well
|
|
273
|
-
* on a second press or when its view activates on a single click; an expandable tree expander
|
|
274
|
-
* toggles its expansion, once per press, and only when it is the widget clicked, so a click on its
|
|
275
|
-
* child falls through to the enclosing row; a notebook tab, clicked directly or through its label,
|
|
276
|
-
* focuses its notebook and switches to its page; a column header sorts by its column. Sorting goes
|
|
277
|
-
* through Gtk.ColumnView.sortByColumn, so the primary sort column and order match what a pointer
|
|
278
|
-
* produces while previously sorted columns are dropped rather than kept as secondary keys. A
|
|
279
|
-
* column-view cell and the row that carries the column headers stand in the way of the click rather
|
|
280
|
-
* than taking it, so a click on either reaches the row or the view behind it.
|
|
281
|
-
*/
|
|
255
|
+
/** Activates or presses and releases a widget. */
|
|
282
256
|
const click = async (widget: Gtk.Widget): Promise<void> => {
|
|
283
257
|
if (!isSelfClickTarget(widget) && (await tryActivate(widget))) {
|
|
284
258
|
return;
|
|
@@ -287,21 +261,9 @@ const click = async (widget: Gtk.Widget): Promise<void> => {
|
|
|
287
261
|
await deliverClick(widget, 1);
|
|
288
262
|
};
|
|
289
263
|
|
|
290
|
-
/**
|
|
291
|
-
* Delivers a two-press click gesture the way {@link click} delivers a single press, without trying
|
|
292
|
-
* activation first. A list box row or flow box child the presses reach, clicked directly or through
|
|
293
|
-
* a descendant, is activated and exclusively selected, as GTK's double-click path does whether or
|
|
294
|
-
* not the container activates on a single click. A widget whose click GTK4 implements itself
|
|
295
|
-
* receives that outcome once per press, so a list, grid, or column-view row is selected and then
|
|
296
|
-
* activated by the second press, a tree expander ends back where it started, a notebook tab stays on
|
|
297
|
-
* the page the first press opened, and a column header sorts and then inverts its order.
|
|
298
|
-
*/
|
|
264
|
+
/** Delivers a double-click gesture. */
|
|
299
265
|
const dblClick = (widget: Gtk.Widget): Promise<void> => deliverClick(widget, 2);
|
|
300
|
-
/**
|
|
301
|
-
* Delivers a three-press click gesture the same way a double click is delivered, applying the same
|
|
302
|
-
* outcome to a list box row or flow box child the presses reach, and applying the outcome GTK4
|
|
303
|
-
* implements itself once per press to a row, tree expander, notebook tab, or column header.
|
|
304
|
-
*/
|
|
266
|
+
/** Delivers a triple-click gesture. */
|
|
305
267
|
const tripleClick = (widget: Gtk.Widget): Promise<void> => deliverClick(widget, 3);
|
|
306
268
|
|
|
307
269
|
export { clickGestures, emitClickPhase, getAuthoredClickGestures, click, dblClick, tripleClick };
|
|
@@ -83,56 +83,38 @@ const buildDropValue = (content: DropContent): GObject.Value => {
|
|
|
83
83
|
});
|
|
84
84
|
};
|
|
85
85
|
|
|
86
|
-
/**
|
|
86
|
+
/** Enters a widget. */
|
|
87
87
|
const hover = (widget: Gtk.Widget): Promise<void> =>
|
|
88
88
|
dispatchOnOrCreateControllers(widget, Gtk.EventControllerMotion, (controller) => {
|
|
89
89
|
controller.emit("enter", 0, 0);
|
|
90
90
|
});
|
|
91
91
|
|
|
92
|
-
/**
|
|
92
|
+
/** Leaves a widget. */
|
|
93
93
|
const unhover = (widget: Gtk.Widget): Promise<void> =>
|
|
94
94
|
dispatchOnOrCreateControllers(widget, Gtk.EventControllerMotion, (controller) => {
|
|
95
95
|
controller.emit("leave");
|
|
96
96
|
});
|
|
97
97
|
|
|
98
|
-
/**
|
|
99
|
-
* Emits `angle-changed` on the widget's rotate gestures.
|
|
100
|
-
*
|
|
101
|
-
* @param angle Current angle, in radians.
|
|
102
|
-
* @param deltaAngle Difference from the angle the gesture started at; defaults to `angle`.
|
|
103
|
-
* @throws When the widget has no Gtk.GestureRotate.
|
|
104
|
-
*/
|
|
98
|
+
/** Rotates a widget's gestures. */
|
|
105
99
|
const rotate = (widget: Gtk.Widget, angle: number, deltaAngle: number = angle): Promise<void> =>
|
|
106
100
|
dispatchOnControllers(widget, Gtk.GestureRotate, (controller) => {
|
|
107
101
|
controller.emit("angle-changed", angle, deltaAngle);
|
|
108
102
|
},
|
|
109
103
|
);
|
|
110
104
|
|
|
111
|
-
/**
|
|
112
|
-
* Emits `scale-changed` with the given scale delta on the widget's zoom gestures.
|
|
113
|
-
*
|
|
114
|
-
* @throws When the widget has no Gtk.GestureZoom.
|
|
115
|
-
*/
|
|
105
|
+
/** Zooms a widget's gestures. */
|
|
116
106
|
const zoom = (widget: Gtk.Widget, scale: number): Promise<void> =>
|
|
117
107
|
dispatchOnControllers(widget, Gtk.GestureZoom, (controller) => {
|
|
118
108
|
controller.emit("scale-changed", scale);
|
|
119
109
|
});
|
|
120
110
|
|
|
121
|
-
/**
|
|
122
|
-
* Emits `swipe` with the given per-axis velocity, in pixels per second, on the widget's swipe gestures.
|
|
123
|
-
*
|
|
124
|
-
* @throws When the widget has no Gtk.GestureSwipe.
|
|
125
|
-
*/
|
|
111
|
+
/** Swipes a widget's gestures. */
|
|
126
112
|
const swipe = (widget: Gtk.Widget, velocityX: number, velocityY: number): Promise<void> =>
|
|
127
113
|
dispatchOnControllers(widget, Gtk.GestureSwipe, (controller) => {
|
|
128
114
|
controller.emit("swipe", velocityX, velocityY);
|
|
129
115
|
});
|
|
130
116
|
|
|
131
|
-
/**
|
|
132
|
-
* Emits `pressed` at the given point in widget coordinates on the widget's long-press gestures.
|
|
133
|
-
*
|
|
134
|
-
* @throws When the widget has no Gtk.GestureLongPress.
|
|
135
|
-
*/
|
|
117
|
+
/** Long-presses a widget. */
|
|
136
118
|
const longPress = (widget: Gtk.Widget, x = 0, y = 0): Promise<void> =>
|
|
137
119
|
dispatchOnControllers(widget, Gtk.GestureLongPress, (controller) => {
|
|
138
120
|
controller.emit("pressed", x, y);
|
|
@@ -219,14 +201,7 @@ const resolveDragUpdates = (dx: number, dy: number, options: DragOptions): DragO
|
|
|
219
201
|
return updates;
|
|
220
202
|
};
|
|
221
203
|
|
|
222
|
-
/**
|
|
223
|
-
* Runs a `drag-begin`, `drag-update`, `drag-end` sequence ending at the offset `dx`, `dy` on the
|
|
224
|
-
* widget's drag gestures, overriding each gesture's start point and offset for the duration so
|
|
225
|
-
* handlers read the simulated values back.
|
|
226
|
-
*
|
|
227
|
-
* @throws When the widget is a Gtk.Range, whose slider reads pointer coordinates from the display,
|
|
228
|
-
* or when it has no Gtk.GestureDrag.
|
|
229
|
-
*/
|
|
204
|
+
/** Drags a widget by an offset. */
|
|
230
205
|
const drag = async (widget: Gtk.Widget, dx: number, dy: number, options: DragOptions = {}): Promise<void> => {
|
|
231
206
|
if (widget instanceof Gtk.Range) {
|
|
232
207
|
throw new TypeError(
|
|
@@ -252,22 +227,13 @@ const emitDrop = (target: Gtk.Widget, content: DropContent, options: DropOptions
|
|
|
252
227
|
}
|
|
253
228
|
};
|
|
254
229
|
|
|
255
|
-
/**
|
|
256
|
-
* Emits `drop` with the given content on every drop target attached to the widget.
|
|
257
|
-
*
|
|
258
|
-
* @throws When the widget has no Gtk.DropTarget.
|
|
259
|
-
*/
|
|
230
|
+
/** Drops content on a widget. */
|
|
260
231
|
const drop = (widget: Gtk.Widget, content: DropContent, options: DropOptions = {}): Promise<void> =>
|
|
261
232
|
wrapEvent(widget, () => {
|
|
262
233
|
emitDrop(widget, content, options);
|
|
263
234
|
});
|
|
264
235
|
|
|
265
|
-
/**
|
|
266
|
-
* Emits `drop` with the given content on the target's drop targets, after checking that the source
|
|
267
|
-
* carries a drag source.
|
|
268
|
-
*
|
|
269
|
-
* @throws When the source has no Gtk.DragSource, or the target no Gtk.DropTarget.
|
|
270
|
-
*/
|
|
236
|
+
/** Drags content from one widget and drops it on another. */
|
|
271
237
|
const dragAndDrop = async (
|
|
272
238
|
source: Gtk.Widget,
|
|
273
239
|
target: Gtk.Widget,
|