@gtkx/testing 1.0.0 → 1.2.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 +1 -1
- package/dist/act.d.ts +1 -3
- package/dist/act.d.ts.map +1 -1
- package/dist/act.js +1 -1
- package/dist/act.js.map +1 -1
- package/dist/build-queries.d.ts +1 -1
- package/dist/build-queries.js +1 -1
- package/dist/build-queries.js.map +1 -1
- package/dist/config.d.ts +8 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/frame-sync.d.ts +2 -2
- package/dist/frame-sync.d.ts.map +1 -1
- package/dist/frame-sync.js +10 -10
- package/dist/frame-sync.js.map +1 -1
- package/dist/harness-window.d.ts +2 -1
- package/dist/harness-window.d.ts.map +1 -1
- package/dist/harness-window.js +12 -1
- package/dist/harness-window.js.map +1 -1
- package/dist/internal.d.ts +1 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +1 -0
- package/dist/internal.js.map +1 -1
- package/dist/matchers.d.ts.map +1 -1
- package/dist/matchers.js +22 -2
- package/dist/matchers.js.map +1 -1
- package/dist/pretty-widget.d.ts.map +1 -1
- package/dist/pretty-widget.js +2 -1
- package/dist/pretty-widget.js.map +1 -1
- package/dist/production.d.ts.map +1 -1
- package/dist/production.js +2 -2
- package/dist/production.js.map +1 -1
- package/dist/render.d.ts +12 -1
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +45 -11
- package/dist/render.js.map +1 -1
- package/dist/role-helpers.d.ts.map +1 -1
- package/dist/role-helpers.js +2 -1
- package/dist/role-helpers.js.map +1 -1
- package/dist/screenshot.d.ts.map +1 -1
- package/dist/screenshot.js +8 -14
- package/dist/screenshot.js.map +1 -1
- package/dist/timers.d.ts +9 -0
- package/dist/timers.d.ts.map +1 -0
- package/dist/timers.js +21 -0
- package/dist/timers.js.map +1 -0
- package/dist/traversal.d.ts +4 -1
- package/dist/traversal.d.ts.map +1 -1
- package/dist/traversal.js +16 -1
- package/dist/traversal.js.map +1 -1
- package/dist/types.d.ts +6 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/user-event/adjustment.d.ts.map +1 -1
- package/dist/user-event/adjustment.js +2 -1
- package/dist/user-event/adjustment.js.map +1 -1
- package/dist/user-event/click.d.ts +5 -4
- package/dist/user-event/click.d.ts.map +1 -1
- package/dist/user-event/click.js +5 -4
- package/dist/user-event/click.js.map +1 -1
- package/dist/user-event/column-header-click.d.ts.map +1 -1
- package/dist/user-event/column-header-click.js +2 -12
- package/dist/user-event/column-header-click.js.map +1 -1
- package/dist/user-event/event-wrapper.d.ts.map +1 -1
- package/dist/user-event/event-wrapper.js +34 -21
- package/dist/user-event/event-wrapper.js.map +1 -1
- package/dist/user-event/index.d.ts +36 -10
- package/dist/user-event/index.d.ts.map +1 -1
- package/dist/user-event/index.js +4 -3
- package/dist/user-event/index.js.map +1 -1
- package/dist/user-event/keyboard.d.ts.map +1 -1
- package/dist/user-event/keyboard.js +93 -38
- package/dist/user-event/keyboard.js.map +1 -1
- package/dist/user-event/list-row-click.d.ts.map +1 -1
- package/dist/user-event/list-row-click.js +4 -5
- package/dist/user-event/list-row-click.js.map +1 -1
- package/dist/user-event/native-click.d.ts.map +1 -1
- package/dist/user-event/native-click.js +4 -0
- package/dist/user-event/native-click.js.map +1 -1
- package/dist/user-event/notebook-tab-click.d.ts +5 -0
- package/dist/user-event/notebook-tab-click.d.ts.map +1 -0
- package/dist/user-event/notebook-tab-click.js +39 -0
- package/dist/user-event/notebook-tab-click.js.map +1 -0
- package/dist/user-event/text.d.ts +6 -3
- package/dist/user-event/text.d.ts.map +1 -1
- package/dist/user-event/text.js +88 -33
- package/dist/user-event/text.js.map +1 -1
- package/dist/wait-for.d.ts.map +1 -1
- package/dist/wait-for.js +4 -3
- package/dist/wait-for.js.map +1 -1
- package/dist/widget-getters.d.ts +4 -1
- package/dist/widget-getters.d.ts.map +1 -1
- package/dist/widget-getters.js +29 -2
- package/dist/widget-getters.js.map +1 -1
- package/dist/window-state.d.ts +10 -0
- package/dist/window-state.d.ts.map +1 -0
- package/dist/window-state.js +41 -0
- package/dist/window-state.js.map +1 -0
- package/package.json +15 -7
- package/src/act.ts +1 -1
- package/src/build-queries.ts +1 -1
- package/src/config.ts +10 -1
- package/src/frame-sync.ts +15 -10
- package/src/harness-window.ts +15 -1
- package/src/internal.ts +1 -0
- package/src/matchers.ts +29 -2
- package/src/pretty-widget.ts +2 -1
- package/src/production.ts +2 -3
- package/src/render.tsx +67 -12
- package/src/role-helpers.ts +2 -1
- package/src/screenshot.ts +10 -17
- package/src/timers.ts +31 -0
- package/src/traversal.ts +22 -0
- package/src/types.ts +6 -1
- package/src/user-event/adjustment.ts +2 -1
- package/src/user-event/click.ts +5 -4
- package/src/user-event/column-header-click.ts +2 -16
- package/src/user-event/event-wrapper.ts +41 -25
- package/src/user-event/index.ts +40 -13
- package/src/user-event/keyboard.ts +124 -54
- package/src/user-event/list-row-click.ts +4 -7
- package/src/user-event/native-click.ts +5 -0
- package/src/user-event/notebook-tab-click.ts +57 -0
- package/src/user-event/text.ts +113 -38
- package/src/wait-for.ts +4 -4
- package/src/widget-getters.ts +55 -2
- package/src/window-state.ts +70 -0
package/dist/user-event/text.js
CHANGED
|
@@ -8,27 +8,93 @@ import { callBooleanGetter } from "../widget-getters.js";
|
|
|
8
8
|
import { wrapEvent } from "./event-wrapper.js";
|
|
9
9
|
const EDITABLE_REQUIRED = `expected editable widget (${formatRoleList(EDITABLE_ROLES)})`;
|
|
10
10
|
const CLEAR_REFUSED = "Cannot clear element: the widget refuses to delete part of its text";
|
|
11
|
-
const
|
|
11
|
+
const SELECTION_DELETE_COUNT = 1;
|
|
12
|
+
const SINGLE_CHARACTER_LENGTH = 1;
|
|
13
|
+
const TEXT_END_POSITION = -1;
|
|
14
|
+
const isWidgetEditable = (widget) => callBooleanGetter(widget, "getEditable") ?? true;
|
|
15
|
+
const readSelection = (widget) => getWidgetSelection(widget) ?? "";
|
|
16
|
+
const hasSelectedText = (widget) => widget.getSelectionBounds()[0];
|
|
17
|
+
const getDelegateText = (widget) => {
|
|
18
|
+
const delegate = getEditableDelegate(widget) ?? widget;
|
|
19
|
+
return delegate instanceof Gtk.Text ? delegate : null;
|
|
20
|
+
};
|
|
21
|
+
const getSelectionLength = (buffer) => {
|
|
22
|
+
const [isSelected, start, end] = buffer.getSelectionBounds();
|
|
23
|
+
return isSelected ? end.getOffset() - start.getOffset() : 0;
|
|
24
|
+
};
|
|
25
|
+
const deleteSelection = (widget) => {
|
|
12
26
|
if (widget instanceof Gtk.TextView) {
|
|
13
|
-
widget.
|
|
27
|
+
widget.getBuffer().deleteSelection(false, true);
|
|
14
28
|
return;
|
|
15
29
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
30
|
+
widget.deleteSelection();
|
|
31
|
+
};
|
|
32
|
+
const focusPlainEditable = (widget) => {
|
|
33
|
+
const [isSelected, start, end] = widget.getSelectionBounds();
|
|
34
|
+
widget.grabFocus();
|
|
35
|
+
if (isSelected) {
|
|
36
|
+
widget.selectRegion(start, end);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
widget.setPosition(TEXT_END_POSITION);
|
|
40
|
+
};
|
|
41
|
+
const focusEditable = (widget) => {
|
|
42
|
+
if (widget instanceof Gtk.TextView) {
|
|
43
|
+
widget.grabFocus();
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const target = getDelegateText(widget);
|
|
47
|
+
if (target === null) {
|
|
48
|
+
focusPlainEditable(widget);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
target.grabFocusWithoutSelecting();
|
|
52
|
+
if (!hasSelectedText(widget)) {
|
|
53
|
+
widget.setPosition(TEXT_END_POSITION);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
const insertTextViewText = (widget, text, kind) => {
|
|
57
|
+
const buffer = widget.getBuffer();
|
|
58
|
+
const length = getSelectionLength(buffer);
|
|
59
|
+
buffer.beginUserAction();
|
|
60
|
+
if (length > 0) {
|
|
61
|
+
widget.emit("delete-from-cursor", Gtk.DeleteType.CHARS, SELECTION_DELETE_COUNT);
|
|
62
|
+
if (kind === "typing" && length > SINGLE_CHARACTER_LENGTH) {
|
|
63
|
+
buffer.endUserAction();
|
|
64
|
+
buffer.beginUserAction();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
widget.emit("insert-at-cursor", text);
|
|
68
|
+
buffer.endUserAction();
|
|
69
|
+
};
|
|
70
|
+
const insertDelegateText = (target, text) => {
|
|
71
|
+
if (hasSelectedText(target)) {
|
|
72
|
+
target.emit("delete-from-cursor", Gtk.DeleteType.CHARS, SELECTION_DELETE_COUNT);
|
|
73
|
+
}
|
|
74
|
+
target.emit("insert-at-cursor", text);
|
|
75
|
+
};
|
|
76
|
+
const insertPlainText = (widget, text) => {
|
|
77
|
+
if (!isWidgetEditable(widget)) {
|
|
19
78
|
return;
|
|
20
79
|
}
|
|
80
|
+
if (hasSelectedText(widget)) {
|
|
81
|
+
widget.deleteSelection();
|
|
82
|
+
}
|
|
21
83
|
const position = widget.getPosition();
|
|
22
84
|
const newPosition = widget.insertText(text, text.length, position);
|
|
23
85
|
widget.setPosition(newPosition);
|
|
24
86
|
};
|
|
25
|
-
const
|
|
26
|
-
const deleteSelection = (widget) => {
|
|
87
|
+
const insertEditableText = (widget, text, kind) => {
|
|
27
88
|
if (widget instanceof Gtk.TextView) {
|
|
28
|
-
widget
|
|
89
|
+
insertTextViewText(widget, text, kind);
|
|
29
90
|
return;
|
|
30
91
|
}
|
|
31
|
-
widget
|
|
92
|
+
const target = getDelegateText(widget);
|
|
93
|
+
if (target === null) {
|
|
94
|
+
insertPlainText(widget, text);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
insertDelegateText(target, text);
|
|
32
98
|
};
|
|
33
99
|
const deleteAllText = (widget) => {
|
|
34
100
|
if (widget instanceof Gtk.TextView) {
|
|
@@ -38,20 +104,6 @@ const deleteAllText = (widget) => {
|
|
|
38
104
|
}
|
|
39
105
|
widget.deleteText(0, -1);
|
|
40
106
|
};
|
|
41
|
-
const applyTextViewSelection = (widget, start, end) => {
|
|
42
|
-
const buffer = widget.getBuffer();
|
|
43
|
-
buffer.selectRange(buffer.getIterAtOffset(start), buffer.getIterAtOffset(end));
|
|
44
|
-
if (end !== start) {
|
|
45
|
-
deleteSelection(widget);
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
const applyEditableSelection = (widget, start, end) => {
|
|
49
|
-
widget.selectRegion(start, end);
|
|
50
|
-
if (end !== start) {
|
|
51
|
-
widget.deleteSelection();
|
|
52
|
-
}
|
|
53
|
-
widget.setPosition(start);
|
|
54
|
-
};
|
|
55
107
|
const applyInitialSelection = (widget, options) => {
|
|
56
108
|
if (options.initialSelectionStart === undefined) {
|
|
57
109
|
return;
|
|
@@ -59,10 +111,11 @@ const applyInitialSelection = (widget, options) => {
|
|
|
59
111
|
const start = options.initialSelectionStart;
|
|
60
112
|
const end = options.initialSelectionEnd ?? start;
|
|
61
113
|
if (widget instanceof Gtk.TextView) {
|
|
62
|
-
|
|
114
|
+
const buffer = widget.getBuffer();
|
|
115
|
+
buffer.selectRange(buffer.getIterAtOffset(start), buffer.getIterAtOffset(end));
|
|
63
116
|
return;
|
|
64
117
|
}
|
|
65
|
-
|
|
118
|
+
widget.selectRegion(start, end);
|
|
66
119
|
};
|
|
67
120
|
const writeClipboardText = (widget, text) => {
|
|
68
121
|
const value = GObject.buildValue(GObject.TYPE_STRING, (v) => {
|
|
@@ -80,19 +133,21 @@ const runEditableEvent = (widget, failure, action) => wrapEvent(widget, () => {
|
|
|
80
133
|
action(widget);
|
|
81
134
|
});
|
|
82
135
|
/**
|
|
83
|
-
* Focuses the widget unless `shouldFocus` is false, applies any initial selection, and inserts the
|
|
84
|
-
* at the cursor
|
|
136
|
+
* Focuses the widget unless `shouldFocus` is false, applies any initial selection, and inserts the
|
|
137
|
+
* text at the cursor, deleting the text the widget has selected first, the way typing over a
|
|
138
|
+
* selection does in GTK4. Focusing works the way clicking into the widget does, leaving its text
|
|
139
|
+
* unselected: a `Gtk.Editable` takes its caret to the end of its text, a `Gtk.TextView` keeps the
|
|
140
|
+
* caret where it stands, and the replaced text stays on the widget's undo stack either way.
|
|
85
141
|
*
|
|
86
142
|
* @throws When the widget is neither a Gtk.Editable nor a Gtk.TextView.
|
|
87
143
|
*/
|
|
88
144
|
const type = (widget, text, options) => runEditableEvent(widget, "Cannot type into element", (editable) => {
|
|
89
145
|
if (options?.shouldFocus ?? true) {
|
|
90
|
-
editable
|
|
146
|
+
focusEditable(editable);
|
|
91
147
|
}
|
|
92
148
|
applyInitialSelection(editable, options ?? {});
|
|
93
|
-
insertEditableText(editable, text);
|
|
149
|
+
insertEditableText(editable, text, "typing");
|
|
94
150
|
});
|
|
95
|
-
const isWidgetEditable = (widget) => callBooleanGetter(widget, "getEditable") ?? true;
|
|
96
151
|
const hasNonEditableChar = (iter, isDefaultEditable) => {
|
|
97
152
|
while (!iter.isEnd()) {
|
|
98
153
|
if (!iter.editable(isDefaultEditable)) {
|
|
@@ -136,7 +191,7 @@ const didDeleteAllText = (widget) => {
|
|
|
136
191
|
};
|
|
137
192
|
const clearEditable = (editable) => {
|
|
138
193
|
requireClearableText(editable);
|
|
139
|
-
editable
|
|
194
|
+
focusEditable(editable);
|
|
140
195
|
if (readEditableText(editable) === "") {
|
|
141
196
|
return;
|
|
142
197
|
}
|
|
@@ -173,7 +228,7 @@ const cut = (widget) => runEditableEvent(widget, "Cannot cut", (editable) => {
|
|
|
173
228
|
});
|
|
174
229
|
/**
|
|
175
230
|
* Inserts the given text at an editable widget's cursor, reading the clipboard instead when no text
|
|
176
|
-
* is given.
|
|
231
|
+
* is given, and deleting the text the widget has selected first, the way a paste does in GTK4.
|
|
177
232
|
*
|
|
178
233
|
* @throws When the widget is neither a Gtk.Editable nor a Gtk.TextView.
|
|
179
234
|
*/
|
|
@@ -183,7 +238,7 @@ const paste = async (widget, text) => {
|
|
|
183
238
|
}
|
|
184
239
|
const content = text ?? (await widget.getClipboard().readTextAsync(null)) ?? "";
|
|
185
240
|
await wrapEvent(widget, () => {
|
|
186
|
-
insertEditableText(widget, content);
|
|
241
|
+
insertEditableText(widget, content, "pasting");
|
|
187
242
|
});
|
|
188
243
|
};
|
|
189
244
|
export { resetClipboard, type, clear, copy, cut, paste };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/user-event/text.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Gdk from \"@gtkx/gi/gdk\";\nimport * as GObject from \"@gtkx/gi/gobject\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport { EDITABLE_ROLES, type EditableTarget, getEditableDelegate, isEditable, readEditableText } from \"../editable.js\";\nimport { formatRoleList } from \"../role-helpers.js\";\nimport { getWidgetSelection } from \"../widget-accessible-properties.js\";\nimport { callBooleanGetter } from \"../widget-getters.js\";\nimport { wrapEvent } from \"./event-wrapper.js\";\n\ntype SignalWatchTarget = {\n on(signal: string, handler: (...args: unknown[]) => unknown, isAfter?: boolean): unknown;\n off(signal: string, handler: (...args: unknown[]) => unknown): unknown;\n};\n\n/** Options for `userEvent.type`. */\ntype TypeOptions = {\n /** Focus the widget before typing; defaults to true. */\n shouldFocus?: boolean | undefined;\n /** Select from this offset before typing, replacing the selected range with the typed text. */\n initialSelectionStart?: number | undefined;\n /** End offset of the initial selection (defaults to the start offset). */\n initialSelectionEnd?: number | undefined;\n};\n\nconst EDITABLE_REQUIRED = `expected editable widget (${formatRoleList(EDITABLE_ROLES)})`;\nconst CLEAR_REFUSED = \"Cannot clear element: the widget refuses to delete part of its text\";\n\nconst insertEditableText = (widget: EditableTarget, text: string): void => {\n if (widget instanceof Gtk.TextView) {\n widget.emit(\"insert-at-cursor\", text);\n\n return;\n }\n\n const target = getEditableDelegate(widget) ?? widget;\n\n if (target instanceof Gtk.Text) {\n target.emit(\"insert-at-cursor\", text);\n\n return;\n }\n\n const position = widget.getPosition();\n const newPosition = widget.insertText(text, text.length, position);\n widget.setPosition(newPosition);\n};\n\nconst readSelection = (widget: EditableTarget): string => getWidgetSelection(widget) ?? \"\";\n\nconst deleteSelection = (widget: EditableTarget): void => {\n if (widget instanceof Gtk.TextView) {\n widget.getBuffer().deleteSelection(false, true);\n\n return;\n }\n\n widget.deleteSelection();\n};\n\nconst deleteAllText = (widget: EditableTarget): void => {\n if (widget instanceof Gtk.TextView) {\n const buffer = widget.getBuffer();\n buffer.deleteInteractive(buffer.getStartIter(), buffer.getEndIter(), widget.getEditable());\n\n return;\n }\n\n widget.deleteText(0, -1);\n};\n\nconst applyTextViewSelection = (widget: Gtk.TextView, start: number, end: number): void => {\n const buffer = widget.getBuffer();\n buffer.selectRange(buffer.getIterAtOffset(start), buffer.getIterAtOffset(end));\n\n if (end !== start) {\n deleteSelection(widget);\n }\n};\n\nconst applyEditableSelection = (widget: Gtk.Editable, start: number, end: number): void => {\n widget.selectRegion(start, end);\n\n if (end !== start) {\n widget.deleteSelection();\n }\n\n widget.setPosition(start);\n};\n\nconst applyInitialSelection = (widget: EditableTarget, options: TypeOptions): void => {\n if (options.initialSelectionStart === undefined) {\n return;\n }\n\n const start = options.initialSelectionStart;\n const end = options.initialSelectionEnd ?? start;\n\n if (widget instanceof Gtk.TextView) {\n applyTextViewSelection(widget, start, end);\n\n return;\n }\n\n applyEditableSelection(widget, start, end);\n};\n\nconst writeClipboardText = (widget: Gtk.Widget, text: string): void => {\n const value = GObject.buildValue(GObject.TYPE_STRING, (v) => {\n v.setString(text);\n });\n\n widget.getClipboard().set(value);\n};\n\nconst resetClipboard = (): void => {\n Gdk.Display.getDefault()?.getClipboard().setContent(null);\n};\n\nconst runEditableEvent = (\n widget: Gtk.Widget,\n failure: string,\n action: (editable: EditableTarget) => void,\n): Promise<void> =>\n wrapEvent(widget, () => {\n if (!isEditable(widget)) {\n throw new Error(`${failure}: ${EDITABLE_REQUIRED}`);\n }\n\n action(widget);\n });\n\n/**\n * Focuses the widget unless `shouldFocus` is false, applies any initial selection, and inserts the text\n * at the cursor.\n *\n * @throws When the widget is neither a Gtk.Editable nor a Gtk.TextView.\n */\nconst type = (widget: Gtk.Widget, text: string, options?: TypeOptions): Promise<void> =>\n runEditableEvent(widget, \"Cannot type into element\", (editable) => {\n if (options?.shouldFocus ?? true) {\n editable.grabFocus();\n }\n\n applyInitialSelection(editable, options ?? {});\n insertEditableText(editable, text);\n });\n\nconst isWidgetEditable = (widget: Gtk.Widget): boolean => callBooleanGetter(widget, \"getEditable\") ?? true;\n\nconst hasNonEditableChar = (iter: Gtk.TextIter, isDefaultEditable: boolean): boolean => {\n while (!iter.isEnd()) {\n if (!iter.editable(isDefaultEditable)) {\n return true;\n }\n\n if (!iter.forwardChar()) {\n return false;\n }\n }\n\n return false;\n};\n\nconst hasProtectedText = (widget: EditableTarget): boolean =>\n widget instanceof Gtk.TextView && hasNonEditableChar(widget.getBuffer().getStartIter(), widget.getEditable());\n\nconst requireClearableText = (editable: EditableTarget): void => {\n if (!isWidgetEditable(editable)) {\n throw new Error(\"Cannot clear element: the widget is not editable\");\n }\n\n if (hasProtectedText(editable)) {\n throw new Error(CLEAR_REFUSED);\n }\n};\n\nconst deletionSignalFor = (widget: EditableTarget): [SignalWatchTarget, string] =>\n widget instanceof Gtk.TextView ? [widget.getBuffer(), \"delete-range\"] : [widget, \"delete-text\"];\n\nconst isDeletionApplied = (emitter: SignalWatchTarget, signal: string, apply: () => void): boolean => {\n let isApplied = false;\n\n const watch = (): void => {\n isApplied = true;\n };\n\n emitter.on(signal, watch, true);\n\n try {\n apply();\n } finally {\n emitter.off(signal, watch);\n }\n\n return isApplied;\n};\n\nconst didDeleteAllText = (widget: EditableTarget): boolean => {\n const [emitter, signal] = deletionSignalFor(widget);\n\n return isDeletionApplied(emitter, signal, () => {\n deleteAllText(widget);\n });\n};\n\nconst clearEditable = (editable: EditableTarget): void => {\n requireClearableText(editable);\n editable.grabFocus();\n\n if (readEditableText(editable) === \"\") {\n return;\n }\n\n if (!didDeleteAllText(editable)) {\n throw new Error(CLEAR_REFUSED);\n }\n};\n\n/**\n * Focuses an editable widget and deletes its whole text through the widget's own editing API, so the\n * deletion emits the signals an edit made by hand emits. Text a tag protects is detected before the\n * deletion runs, leaving such a widget untouched. A widget that writes a new value back in response\n * to the deletion, as an input mask does, is cleared successfully and keeps whatever it wrote.\n *\n * @throws When the widget is neither a Gtk.Editable nor a Gtk.TextView, when it refuses edits, when\n * a tag protects part of its text, or when a handler blocks the deletion.\n */\nconst clear = (widget: Gtk.Widget): Promise<void> =>\n runEditableEvent(widget, \"Cannot clear element\", clearEditable);\n\n/**\n * Writes an editable widget's selected text to its clipboard, or the empty string when nothing is selected.\n *\n * @throws When the widget is neither a Gtk.Editable nor a Gtk.TextView.\n */\nconst copy = (widget: Gtk.Widget): Promise<void> =>\n runEditableEvent(widget, \"Cannot copy\", (editable) => {\n writeClipboardText(editable, readSelection(editable));\n });\n\n/**\n * Writes an editable widget's selected text to its clipboard, then deletes that selection.\n *\n * @throws When the widget is neither a Gtk.Editable nor a Gtk.TextView.\n */\nconst cut = (widget: Gtk.Widget): Promise<void> =>\n runEditableEvent(widget, \"Cannot cut\", (editable) => {\n writeClipboardText(editable, readSelection(editable));\n deleteSelection(editable);\n });\n\n/**\n * Inserts the given text at an editable widget's cursor, reading the clipboard instead when no text\n * is given.\n *\n * @throws When the widget is neither a Gtk.Editable nor a Gtk.TextView.\n */\nconst paste = async (widget: Gtk.Widget, text?: string): Promise<void> => {\n if (!isEditable(widget)) {\n throw new Error(`Cannot paste: ${EDITABLE_REQUIRED}`);\n }\n\n const content = text ?? (await widget.getClipboard().readTextAsync(null)) ?? \"\";\n\n await wrapEvent(widget, () => {\n insertEditableText(widget, content);\n });\n};\n\nexport { resetClipboard, type, clear, copy, cut, paste, type TypeOptions };\n"]}
|
|
1
|
+
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/user-event/text.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Gdk from \"@gtkx/gi/gdk\";\nimport * as GObject from \"@gtkx/gi/gobject\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport { EDITABLE_ROLES, type EditableTarget, getEditableDelegate, isEditable, readEditableText } from \"../editable.js\";\nimport { formatRoleList } from \"../role-helpers.js\";\nimport { getWidgetSelection } from \"../widget-accessible-properties.js\";\nimport { callBooleanGetter } from \"../widget-getters.js\";\nimport { wrapEvent } from \"./event-wrapper.js\";\n\ntype SignalWatchTarget = {\n on(signal: string, handler: (...args: unknown[]) => unknown, isAfter?: boolean): unknown;\n off(signal: string, handler: (...args: unknown[]) => unknown): unknown;\n};\n\ntype InsertKind = \"typing\" | \"pasting\";\n\n/** Options for `userEvent.type`. */\ntype TypeOptions = {\n /** Focus the widget before typing; defaults to true. */\n shouldFocus?: boolean | undefined;\n /** Select from this offset before typing, replacing the selected range with the typed text. */\n initialSelectionStart?: number | undefined;\n /** End offset of the initial selection (defaults to the start offset). */\n initialSelectionEnd?: number | undefined;\n};\n\nconst EDITABLE_REQUIRED = `expected editable widget (${formatRoleList(EDITABLE_ROLES)})`;\nconst CLEAR_REFUSED = \"Cannot clear element: the widget refuses to delete part of its text\";\nconst SELECTION_DELETE_COUNT = 1;\nconst SINGLE_CHARACTER_LENGTH = 1;\nconst TEXT_END_POSITION = -1;\n\nconst isWidgetEditable = (widget: Gtk.Widget): boolean => callBooleanGetter(widget, \"getEditable\") ?? true;\nconst readSelection = (widget: EditableTarget): string => getWidgetSelection(widget) ?? \"\";\nconst hasSelectedText = (widget: Gtk.Editable): boolean => widget.getSelectionBounds()[0];\n\nconst getDelegateText = (widget: Gtk.Editable): Gtk.Text | null => {\n const delegate = getEditableDelegate(widget) ?? widget;\n\n return delegate instanceof Gtk.Text ? delegate : null;\n};\n\nconst getSelectionLength = (buffer: Gtk.TextBuffer): number => {\n const [isSelected, start, end] = buffer.getSelectionBounds();\n\n return isSelected ? end.getOffset() - start.getOffset() : 0;\n};\n\nconst deleteSelection = (widget: EditableTarget): void => {\n if (widget instanceof Gtk.TextView) {\n widget.getBuffer().deleteSelection(false, true);\n\n return;\n }\n\n widget.deleteSelection();\n};\n\nconst focusPlainEditable = (widget: Gtk.Editable): void => {\n const [isSelected, start, end] = widget.getSelectionBounds();\n widget.grabFocus();\n\n if (isSelected) {\n widget.selectRegion(start, end);\n\n return;\n }\n\n widget.setPosition(TEXT_END_POSITION);\n};\n\nconst focusEditable = (widget: EditableTarget): void => {\n if (widget instanceof Gtk.TextView) {\n widget.grabFocus();\n\n return;\n }\n\n const target = getDelegateText(widget);\n\n if (target === null) {\n focusPlainEditable(widget);\n\n return;\n }\n\n target.grabFocusWithoutSelecting();\n\n if (!hasSelectedText(widget)) {\n widget.setPosition(TEXT_END_POSITION);\n }\n};\n\nconst insertTextViewText = (widget: Gtk.TextView, text: string, kind: InsertKind): void => {\n const buffer = widget.getBuffer();\n const length = getSelectionLength(buffer);\n buffer.beginUserAction();\n\n if (length > 0) {\n widget.emit(\"delete-from-cursor\", Gtk.DeleteType.CHARS, SELECTION_DELETE_COUNT);\n\n if (kind === \"typing\" && length > SINGLE_CHARACTER_LENGTH) {\n buffer.endUserAction();\n buffer.beginUserAction();\n }\n }\n\n widget.emit(\"insert-at-cursor\", text);\n buffer.endUserAction();\n};\n\nconst insertDelegateText = (target: Gtk.Text, text: string): void => {\n if (hasSelectedText(target)) {\n target.emit(\"delete-from-cursor\", Gtk.DeleteType.CHARS, SELECTION_DELETE_COUNT);\n }\n\n target.emit(\"insert-at-cursor\", text);\n};\n\nconst insertPlainText = (widget: Gtk.Editable, text: string): void => {\n if (!isWidgetEditable(widget)) {\n return;\n }\n\n if (hasSelectedText(widget)) {\n widget.deleteSelection();\n }\n\n const position = widget.getPosition();\n const newPosition = widget.insertText(text, text.length, position);\n widget.setPosition(newPosition);\n};\n\nconst insertEditableText = (widget: EditableTarget, text: string, kind: InsertKind): void => {\n if (widget instanceof Gtk.TextView) {\n insertTextViewText(widget, text, kind);\n\n return;\n }\n\n const target = getDelegateText(widget);\n\n if (target === null) {\n insertPlainText(widget, text);\n\n return;\n }\n\n insertDelegateText(target, text);\n};\n\nconst deleteAllText = (widget: EditableTarget): void => {\n if (widget instanceof Gtk.TextView) {\n const buffer = widget.getBuffer();\n buffer.deleteInteractive(buffer.getStartIter(), buffer.getEndIter(), widget.getEditable());\n\n return;\n }\n\n widget.deleteText(0, -1);\n};\n\nconst applyInitialSelection = (widget: EditableTarget, options: TypeOptions): void => {\n if (options.initialSelectionStart === undefined) {\n return;\n }\n\n const start = options.initialSelectionStart;\n const end = options.initialSelectionEnd ?? start;\n\n if (widget instanceof Gtk.TextView) {\n const buffer = widget.getBuffer();\n buffer.selectRange(buffer.getIterAtOffset(start), buffer.getIterAtOffset(end));\n\n return;\n }\n\n widget.selectRegion(start, end);\n};\n\nconst writeClipboardText = (widget: Gtk.Widget, text: string): void => {\n const value = GObject.buildValue(GObject.TYPE_STRING, (v) => {\n v.setString(text);\n });\n\n widget.getClipboard().set(value);\n};\n\nconst resetClipboard = (): void => {\n Gdk.Display.getDefault()?.getClipboard().setContent(null);\n};\n\nconst runEditableEvent = (\n widget: Gtk.Widget,\n failure: string,\n action: (editable: EditableTarget) => void,\n): Promise<void> =>\n wrapEvent(widget, () => {\n if (!isEditable(widget)) {\n throw new Error(`${failure}: ${EDITABLE_REQUIRED}`);\n }\n\n action(widget);\n });\n\n/**\n * Focuses the widget unless `shouldFocus` is false, applies any initial selection, and inserts the\n * text at the cursor, deleting the text the widget has selected first, the way typing over a\n * selection does in GTK4. Focusing works the way clicking into the widget does, leaving its text\n * unselected: a `Gtk.Editable` takes its caret to the end of its text, a `Gtk.TextView` keeps the\n * caret where it stands, and the replaced text stays on the widget's undo stack either way.\n *\n * @throws When the widget is neither a Gtk.Editable nor a Gtk.TextView.\n */\nconst type = (widget: Gtk.Widget, text: string, options?: TypeOptions): Promise<void> =>\n runEditableEvent(widget, \"Cannot type into element\", (editable) => {\n if (options?.shouldFocus ?? true) {\n focusEditable(editable);\n }\n\n applyInitialSelection(editable, options ?? {});\n insertEditableText(editable, text, \"typing\");\n });\n\nconst hasNonEditableChar = (iter: Gtk.TextIter, isDefaultEditable: boolean): boolean => {\n while (!iter.isEnd()) {\n if (!iter.editable(isDefaultEditable)) {\n return true;\n }\n\n if (!iter.forwardChar()) {\n return false;\n }\n }\n\n return false;\n};\n\nconst hasProtectedText = (widget: EditableTarget): boolean =>\n widget instanceof Gtk.TextView && hasNonEditableChar(widget.getBuffer().getStartIter(), widget.getEditable());\n\nconst requireClearableText = (editable: EditableTarget): void => {\n if (!isWidgetEditable(editable)) {\n throw new Error(\"Cannot clear element: the widget is not editable\");\n }\n\n if (hasProtectedText(editable)) {\n throw new Error(CLEAR_REFUSED);\n }\n};\n\nconst deletionSignalFor = (widget: EditableTarget): [SignalWatchTarget, string] =>\n widget instanceof Gtk.TextView ? [widget.getBuffer(), \"delete-range\"] : [widget, \"delete-text\"];\n\nconst isDeletionApplied = (emitter: SignalWatchTarget, signal: string, apply: () => void): boolean => {\n let isApplied = false;\n\n const watch = (): void => {\n isApplied = true;\n };\n\n emitter.on(signal, watch, true);\n\n try {\n apply();\n } finally {\n emitter.off(signal, watch);\n }\n\n return isApplied;\n};\n\nconst didDeleteAllText = (widget: EditableTarget): boolean => {\n const [emitter, signal] = deletionSignalFor(widget);\n\n return isDeletionApplied(emitter, signal, () => {\n deleteAllText(widget);\n });\n};\n\nconst clearEditable = (editable: EditableTarget): void => {\n requireClearableText(editable);\n focusEditable(editable);\n\n if (readEditableText(editable) === \"\") {\n return;\n }\n\n if (!didDeleteAllText(editable)) {\n throw new Error(CLEAR_REFUSED);\n }\n};\n\n/**\n * Focuses an editable widget and deletes its whole text through the widget's own editing API, so the\n * deletion emits the signals an edit made by hand emits. Text a tag protects is detected before the\n * deletion runs, leaving such a widget untouched. A widget that writes a new value back in response\n * to the deletion, as an input mask does, is cleared successfully and keeps whatever it wrote.\n *\n * @throws When the widget is neither a Gtk.Editable nor a Gtk.TextView, when it refuses edits, when\n * a tag protects part of its text, or when a handler blocks the deletion.\n */\nconst clear = (widget: Gtk.Widget): Promise<void> =>\n runEditableEvent(widget, \"Cannot clear element\", clearEditable);\n\n/**\n * Writes an editable widget's selected text to its clipboard, or the empty string when nothing is selected.\n *\n * @throws When the widget is neither a Gtk.Editable nor a Gtk.TextView.\n */\nconst copy = (widget: Gtk.Widget): Promise<void> =>\n runEditableEvent(widget, \"Cannot copy\", (editable) => {\n writeClipboardText(editable, readSelection(editable));\n });\n\n/**\n * Writes an editable widget's selected text to its clipboard, then deletes that selection.\n *\n * @throws When the widget is neither a Gtk.Editable nor a Gtk.TextView.\n */\nconst cut = (widget: Gtk.Widget): Promise<void> =>\n runEditableEvent(widget, \"Cannot cut\", (editable) => {\n writeClipboardText(editable, readSelection(editable));\n deleteSelection(editable);\n });\n\n/**\n * Inserts the given text at an editable widget's cursor, reading the clipboard instead when no text\n * is given, and deleting the text the widget has selected first, the way a paste does in GTK4.\n *\n * @throws When the widget is neither a Gtk.Editable nor a Gtk.TextView.\n */\nconst paste = async (widget: Gtk.Widget, text?: string): Promise<void> => {\n if (!isEditable(widget)) {\n throw new Error(`Cannot paste: ${EDITABLE_REQUIRED}`);\n }\n\n const content = text ?? (await widget.getClipboard().readTextAsync(null)) ?? \"\";\n\n await wrapEvent(widget, () => {\n insertEditableText(widget, content, \"pasting\");\n });\n};\n\nexport { resetClipboard, type, clear, copy, cut, paste, type TypeOptions };\n"]}
|
package/dist/wait-for.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wait-for.d.ts","sourceRoot":"","sources":["../src/wait-for.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,GAAG,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"wait-for.d.ts","sourceRoot":"","sources":["../src/wait-for.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,GAAG,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAOjD,mEAAmE;AACnE,KAAK,aAAa,GAAG,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC;AACtD,4FAA4F;AAC5F,KAAK,iBAAiB,GAAG,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,aAAa,CAAC,CAAC;AA4D3E;;;;;;;GAOG;AACH,QAAA,MAAM,OAAO,GAAI,CAAC,EAAE,UAAU,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,UAAU,cAAc,KAAG,OAAO,CAAC,CAAC,CAoBvF,CAAC;AAyBF;;;;;;;GAOG;AACH,QAAA,MAAM,yBAAyB,GAC3B,mBAAmB,iBAAiB,EACpC,UAAU,cAAc,KACzB,OAAO,CAAC,IAAI,CAmBd,CAAC;AAEF,OAAO,EAAE,OAAO,EAAE,yBAAyB,EAAE,CAAC"}
|
package/dist/wait-for.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { runWithActEnvironment } from "./act.js";
|
|
2
2
|
import { getConfig } from "./config.js";
|
|
3
3
|
import { timeoutError } from "./errors.js";
|
|
4
|
+
import { advanceFakeClock, delay, now } from "./timers.js";
|
|
4
5
|
const DEFAULT_INTERVAL = 50;
|
|
5
6
|
const ELEMENT_NOT_REMOVED = new Error("Element not yet removed");
|
|
6
|
-
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
7
7
|
const copyStackTrace = (target, source) => {
|
|
8
8
|
const { stack } = source;
|
|
9
9
|
if (stack === undefined) {
|
|
@@ -17,9 +17,9 @@ const copyStackTrace = (target, source) => {
|
|
|
17
17
|
target.stack = stack.slice(0, index) + target.message + stack.slice(index + source.message.length);
|
|
18
18
|
};
|
|
19
19
|
const pollUntilSuccess = async (callback, timeout, interval) => {
|
|
20
|
-
const startTime =
|
|
20
|
+
const startTime = now();
|
|
21
21
|
let lastError = null;
|
|
22
|
-
while (
|
|
22
|
+
while (now() - startTime < timeout) {
|
|
23
23
|
try {
|
|
24
24
|
const result = await callback();
|
|
25
25
|
await delay(0);
|
|
@@ -27,6 +27,7 @@ const pollUntilSuccess = async (callback, timeout, interval) => {
|
|
|
27
27
|
}
|
|
28
28
|
catch (error) {
|
|
29
29
|
lastError = error;
|
|
30
|
+
await advanceFakeClock(interval);
|
|
30
31
|
await delay(interval);
|
|
31
32
|
}
|
|
32
33
|
}
|
package/dist/wait-for.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wait-for.js","sourceRoot":"","sources":["../src/wait-for.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"wait-for.js","sourceRoot":"","sources":["../src/wait-for.ts"],"names":[],"mappings":"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","sourcesContent":["import type * as Gtk from \"@gtkx/gi/gtk\";\nimport type { WaitForOptions } from \"./types.js\";\nimport { runWithActEnvironment } from \"./act.js\";\nimport { getConfig } from \"./config.js\";\nimport { timeoutError } from \"./errors.js\";\nimport { advanceFakeClock, delay, now } from \"./timers.js\";\n\ntype PollResult<T> = { status: \"resolved\"; value: T } | { status: \"timedout\"; lastError: Error | null };\n/** Widgets watched for removal; null counts as already removed. */\ntype RemovalTarget = Gtk.Widget | Gtk.Widget[] | null;\n/** The widgets to watch for removal, or a function re-read on every poll to locate them. */\ntype ElementOrCallback = Gtk.Widget | Gtk.Widget[] | (() => RemovalTarget);\n\nconst DEFAULT_INTERVAL = 50;\nconst ELEMENT_NOT_REMOVED = new Error(\"Element not yet removed\");\n\nconst copyStackTrace = (target: Error, source: Error): void => {\n const { stack } = source;\n\n if (stack === undefined) {\n return;\n }\n\n const index = stack.indexOf(source.message);\n\n if (index === -1) {\n target.stack = stack;\n\n return;\n }\n\n target.stack = stack.slice(0, index) + target.message + stack.slice(index + source.message.length);\n};\n\nconst pollUntilSuccess = async <T>(\n callback: () => T | Promise<T>,\n timeout: number,\n interval: number,\n): Promise<PollResult<T>> => {\n const startTime = now();\n let lastError: Error | null = null;\n\n while (now() - startTime < timeout) {\n try {\n const result = await callback();\n await delay(0);\n\n return { status: \"resolved\", value: result };\n } catch (error) {\n lastError = error as Error;\n await advanceFakeClock(interval);\n await delay(interval);\n }\n }\n\n return { status: \"timedout\", lastError };\n};\n\nconst buildTimeoutError = (\n timeout: number,\n lastError: Error | null,\n stackTraceError: Error,\n onTimeout: ((error: Error) => Error) | undefined,\n): Error => {\n const error = timeoutError(timeout, lastError);\n const finalError = onTimeout ? onTimeout(error) : error;\n copyStackTrace(finalError, stackTraceError);\n\n return finalError;\n};\n\n/**\n * Repeatedly invokes a callback until it succeeds without throwing or the\n * timeout elapses, retrying on each rejection at a fixed interval.\n *\n * @param callback The assertion or query to retry; its resolved value is returned.\n * @param options Optional timeout, interval, and timeout error customization.\n * @returns The callback's result once it succeeds.\n */\nconst waitFor = <T>(callback: () => T | Promise<T>, options?: WaitForOptions): Promise<T> => {\n if (typeof callback !== \"function\") {\n throw new TypeError(\"Received `callback` arg must be a function\");\n }\n\n const stackTraceError = options?.stackTraceError ?? new Error(\"STACK_TRACE_MESSAGE\");\n\n return Promise.resolve(\n runWithActEnvironment(false, async () => {\n const config = getConfig();\n const { timeout = config.asyncUtilTimeout, interval = DEFAULT_INTERVAL, onTimeout } = options ?? {};\n const result = await pollUntilSuccess(callback, timeout, interval);\n\n if (result.status === \"resolved\") {\n return result.value;\n }\n\n throw buildTimeoutError(timeout, result.lastError, stackTraceError, onTimeout);\n }),\n );\n};\n\nconst getTarget = (elementOrCallback: ElementOrCallback): RemovalTarget =>\n typeof elementOrCallback === \"function\" ? elementOrCallback() : elementOrCallback;\n\nconst isWidgetRemoved = (widget: Gtk.Widget | null): boolean => {\n if (widget === null) {\n return true;\n }\n\n try {\n return widget.getRoot() === null;\n } catch {\n return true;\n }\n};\n\nconst isTargetRemoved = (target: RemovalTarget): boolean => {\n if (Array.isArray(target)) {\n return target.every((widget) => isWidgetRemoved(widget));\n }\n\n return isWidgetRemoved(target);\n};\n\n/**\n * Waits until the given widget or widgets are detached from the tree. Rejects\n * immediately if the target is already absent when called.\n *\n * @param elementOrCallback The widget, array of widgets, or a function\n * returning them to observe for removal.\n * @param options Optional timeout and interval settings.\n */\nconst waitForElementToBeRemoved = (\n elementOrCallback: ElementOrCallback,\n options?: WaitForOptions,\n): Promise<void> => {\n const stackTraceError = new Error(\"STACK_TRACE_MESSAGE\");\n\n if (isTargetRemoved(getTarget(elementOrCallback))) {\n return Promise.reject(\n new Error(\n \"Element already removed: waitForElementToBeRemoved requires the element to be present initially\",\n ),\n );\n }\n\n return waitFor(\n () => {\n if (!isTargetRemoved(getTarget(elementOrCallback))) {\n throw ELEMENT_NOT_REMOVED;\n }\n },\n { ...options, stackTraceError },\n );\n};\n\nexport { waitFor, waitForElementToBeRemoved };\n"]}
|
package/dist/widget-getters.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import type * as GObject from "@gtkx/gi/gobject";
|
|
1
2
|
import type * as Gtk from "@gtkx/gi/gtk";
|
|
2
3
|
declare const getWidgetTypeName: (widget: Gtk.Widget) => string | null;
|
|
4
|
+
declare const getTypeTag: (object: GObject.Object) => string;
|
|
5
|
+
declare const isDefaultWidgetName: (widget: Gtk.Widget, name: string) => boolean;
|
|
3
6
|
declare const hasWidgetMethod: (widget: Gtk.Widget, name: string) => boolean;
|
|
4
7
|
declare const getCallableMethod: <Args extends unknown[], Result>(widget: Gtk.Widget, name: string) => ((...args: Args) => Result) | null;
|
|
5
8
|
declare const callBooleanGetter: (widget: Gtk.Widget, method: string) => boolean | null;
|
|
6
9
|
declare const callStringGetter: (widget: Gtk.Widget, method: string) => string | null;
|
|
7
|
-
export { callBooleanGetter, callStringGetter, getCallableMethod, getWidgetTypeName, hasWidgetMethod };
|
|
10
|
+
export { callBooleanGetter, callStringGetter, getCallableMethod, getTypeTag, getWidgetTypeName, hasWidgetMethod, isDefaultWidgetName, };
|
|
8
11
|
//# sourceMappingURL=widget-getters.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"widget-getters.d.ts","sourceRoot":"","sources":["../src/widget-getters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,GAAG,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"widget-getters.d.ts","sourceRoot":"","sources":["../src/widget-getters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,OAAO,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,KAAK,GAAG,MAAM,cAAc,CAAC;AAQzC,QAAA,MAAM,iBAAiB,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,MAAM,GAAG,IAAyC,CAAC;AA2BnG,QAAA,MAAM,UAAU,GAAI,QAAQ,OAAO,CAAC,MAAM,KAAG,MAU5C,CAAC;AAEF,QAAA,MAAM,mBAAmB,GAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,MAAM,MAAM,KAAG,OACL,CAAC;AAE5D,QAAA,MAAM,eAAe,GAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,MAAM,MAAM,KAAG,OACL,CAAC;AAGxD,QAAA,MAAM,iBAAiB,GAAI,IAAI,SAAS,OAAO,EAAE,EAAE,MAAM,EACrD,QAAQ,GAAG,CAAC,MAAM,EAClB,MAAM,MAAM,KACb,CAAC,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC,GAAG,IAIhC,CAAC;AAEF,QAAA,MAAM,iBAAiB,GAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,QAAQ,MAAM,KAAG,OAAO,GAAG,IAIzE,CAAC;AAEF,QAAA,MAAM,gBAAgB,GAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,QAAQ,MAAM,KAAG,MAAM,GAAG,IAIvE,CAAC;AAEF,OAAO,EACH,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,EACV,iBAAiB,EACjB,eAAe,EACf,mBAAmB,GACtB,CAAC"}
|
package/dist/widget-getters.js
CHANGED
|
@@ -1,6 +1,33 @@
|
|
|
1
|
-
import { getInstanceType, typeName } from "@gtkx/runtime";
|
|
1
|
+
import { getClassType, getInstanceType, TYPE_INVALID, typeName } from "@gtkx/runtime";
|
|
2
|
+
import { resolveWrapperClass } from "@gtkx/runtime/internal";
|
|
3
|
+
import { walkClassChain } from "@gtkx/utils";
|
|
4
|
+
const UNNAMED_TYPE_TAG = "Object";
|
|
2
5
|
const getWidgetMethod = (widget, name) => Reflect.get(widget, name);
|
|
3
6
|
const getWidgetTypeName = (widget) => typeName(getInstanceType(widget));
|
|
7
|
+
const isClass = (value) => typeof value === "function";
|
|
8
|
+
const nonEmpty = (value) => typeof value === "string" && value.length > 0 ? value : undefined;
|
|
9
|
+
const getObjectClass = (object) => {
|
|
10
|
+
const cls = object.constructor;
|
|
11
|
+
return isClass(cls) ? cls : null;
|
|
12
|
+
};
|
|
13
|
+
const getNearestClassName = (object) => walkClassChain(getObjectClass(object), (ancestor) => nonEmpty(ancestor.name));
|
|
14
|
+
const getUntypedClassName = (object) => {
|
|
15
|
+
const cls = getObjectClass(object);
|
|
16
|
+
return cls !== null && getClassType(cls) === TYPE_INVALID ? nonEmpty(cls.name) : undefined;
|
|
17
|
+
};
|
|
18
|
+
const getExactWrapperName = (type) => {
|
|
19
|
+
const wrapper = resolveWrapperClass(type);
|
|
20
|
+
return wrapper !== null && getClassType(wrapper) === type ? nonEmpty(wrapper.name) : undefined;
|
|
21
|
+
};
|
|
22
|
+
const getTypeTag = (object) => {
|
|
23
|
+
const type = getInstanceType(object);
|
|
24
|
+
return (getUntypedClassName(object) ??
|
|
25
|
+
getExactWrapperName(type) ??
|
|
26
|
+
nonEmpty(typeName(type)) ??
|
|
27
|
+
getNearestClassName(object) ??
|
|
28
|
+
UNNAMED_TYPE_TAG);
|
|
29
|
+
};
|
|
30
|
+
const isDefaultWidgetName = (widget, name) => name.length === 0 || name === getWidgetTypeName(widget);
|
|
4
31
|
const hasWidgetMethod = (widget, name) => typeof getWidgetMethod(widget, name) === "function";
|
|
5
32
|
/* eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters -- callers name the signature */
|
|
6
33
|
const getCallableMethod = (widget, name) => {
|
|
@@ -15,5 +42,5 @@ const callStringGetter = (widget, method) => {
|
|
|
15
42
|
const value = getCallableMethod(widget, method)?.();
|
|
16
43
|
return typeof value === "string" ? value : null;
|
|
17
44
|
};
|
|
18
|
-
export { callBooleanGetter, callStringGetter, getCallableMethod, getWidgetTypeName, hasWidgetMethod };
|
|
45
|
+
export { callBooleanGetter, callStringGetter, getCallableMethod, getTypeTag, getWidgetTypeName, hasWidgetMethod, isDefaultWidgetName, };
|
|
19
46
|
//# sourceMappingURL=widget-getters.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"widget-getters.js","sourceRoot":"","sources":["../src/widget-getters.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"widget-getters.js","sourceRoot":"","sources":["../src/widget-getters.ts"],"names":[],"mappings":"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","sourcesContent":["import type * as GObject from \"@gtkx/gi/gobject\";\nimport type * as Gtk from \"@gtkx/gi/gtk\";\nimport { getClassType, getInstanceType, TYPE_INVALID, typeName } from \"@gtkx/runtime\";\nimport { resolveWrapperClass } from \"@gtkx/runtime/internal\";\nimport { type AnyClass, walkClassChain } from \"@gtkx/utils\";\n\nconst UNNAMED_TYPE_TAG = \"Object\";\n\nconst getWidgetMethod = (widget: Gtk.Widget, name: string): unknown => Reflect.get(widget, name);\nconst getWidgetTypeName = (widget: Gtk.Widget): string | null => typeName(getInstanceType(widget));\nconst isClass = (value: unknown): value is AnyClass => typeof value === \"function\";\n\nconst nonEmpty = (value: unknown): string | undefined =>\n typeof value === \"string\" && value.length > 0 ? value : undefined;\n\nconst getObjectClass = (object: GObject.Object): AnyClass | null => {\n const cls: unknown = object.constructor;\n\n return isClass(cls) ? cls : null;\n};\n\nconst getNearestClassName = (object: GObject.Object): string | undefined =>\n walkClassChain(getObjectClass(object), (ancestor) => nonEmpty(ancestor.name));\n\nconst getUntypedClassName = (object: GObject.Object): string | undefined => {\n const cls = getObjectClass(object);\n\n return cls !== null && getClassType(cls) === TYPE_INVALID ? nonEmpty(cls.name) : undefined;\n};\n\nconst getExactWrapperName = (type: bigint): string | undefined => {\n const wrapper = resolveWrapperClass(type);\n\n return wrapper !== null && getClassType(wrapper) === type ? nonEmpty(wrapper.name) : undefined;\n};\n\nconst getTypeTag = (object: GObject.Object): string => {\n const type = getInstanceType(object);\n\n return (\n getUntypedClassName(object) ??\n getExactWrapperName(type) ??\n nonEmpty(typeName(type)) ??\n getNearestClassName(object) ??\n UNNAMED_TYPE_TAG\n );\n};\n\nconst isDefaultWidgetName = (widget: Gtk.Widget, name: string): boolean =>\n name.length === 0 || name === getWidgetTypeName(widget);\n\nconst hasWidgetMethod = (widget: Gtk.Widget, name: string): boolean =>\n typeof getWidgetMethod(widget, name) === \"function\";\n\n/* eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters -- callers name the signature */\nconst getCallableMethod = <Args extends unknown[], Result>(\n widget: Gtk.Widget,\n name: string,\n): ((...args: Args) => Result) | null => {\n const fn = getWidgetMethod(widget, name);\n\n return typeof fn === \"function\" ? (fn as (...args: Args) => Result).bind(widget) : null;\n};\n\nconst callBooleanGetter = (widget: Gtk.Widget, method: string): boolean | null => {\n const value = getCallableMethod<[], unknown>(widget, method)?.();\n\n return typeof value === \"boolean\" ? value : null;\n};\n\nconst callStringGetter = (widget: Gtk.Widget, method: string): string | null => {\n const value = getCallableMethod<[], unknown>(widget, method)?.();\n\n return typeof value === \"string\" ? value : null;\n};\n\nexport {\n callBooleanGetter,\n callStringGetter,\n getCallableMethod,\n getTypeTag,\n getWidgetTypeName,\n hasWidgetMethod,\n isDefaultWidgetName,\n};\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
2
|
+
declare const mappedToplevels: () => Gtk.Window[];
|
|
3
|
+
declare const isWindowAllocated: (window: Gtk.Window) => boolean;
|
|
4
|
+
declare const activeToplevel: () => Gtk.Window | null;
|
|
5
|
+
declare const isWindowActivated: (window: Gtk.Window) => boolean;
|
|
6
|
+
declare const isWindowBlockedByModal: (window: Gtk.Window) => boolean;
|
|
7
|
+
declare const findPresentedWindowFailure: (window: Gtk.Window) => string | null;
|
|
8
|
+
declare const findRenderedWindowFailure: (window: Gtk.Window) => string | null;
|
|
9
|
+
export { activeToplevel, findPresentedWindowFailure, findRenderedWindowFailure, isWindowActivated, isWindowAllocated, isWindowBlockedByModal, mappedToplevels, };
|
|
10
|
+
//# sourceMappingURL=window-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"window-state.d.ts","sourceRoot":"","sources":["../src/window-state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AASpC,QAAA,MAAM,eAAe,QAAO,GAAG,CAAC,MAAM,EACoE,CAAC;AAE3G,QAAA,MAAM,iBAAiB,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,OAI/C,CAAC;AAEF,QAAA,MAAM,cAAc,QAAO,GAAG,CAAC,MAAM,GAAG,IAAyE,CAAC;AAElH,QAAA,MAAM,iBAAiB,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,OACa,CAAC;AAqB9D,QAAA,MAAM,sBAAsB,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,OAC0B,CAAC;AAEhF,QAAA,MAAM,0BAA0B,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,MAAM,GAAG,IAMjE,CAAC;AAEF,QAAA,MAAM,yBAAyB,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,MAAM,GAAG,IAMhE,CAAC;AAEF,OAAO,EACH,cAAc,EACd,0BAA0B,EAC1B,yBAAyB,EACzB,iBAAiB,EACjB,iBAAiB,EACjB,sBAAsB,EACtB,eAAe,GAClB,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
2
|
+
const WINDOW_NOT_ALLOCATED = "it was never allocated a size";
|
|
3
|
+
const WINDOW_NOT_ACTIVATED = "it never became active";
|
|
4
|
+
const NO_WINDOW_ACTIVATED = "no window of the application ever became active";
|
|
5
|
+
const canDisplayDeliverActivation = (window) => window.getDisplay().getDefaultSeat() !== null;
|
|
6
|
+
const isWindow = (widget) => widget instanceof Gtk.Window;
|
|
7
|
+
const mappedToplevels = () => Gtk.Window.listToplevels().filter((widget) => isWindow(widget)).filter((window) => window.getMapped());
|
|
8
|
+
const isWindowAllocated = (window) => {
|
|
9
|
+
const [isComputed, allocation] = window.computeBounds(window);
|
|
10
|
+
return isComputed && allocation.getWidth() > 0;
|
|
11
|
+
};
|
|
12
|
+
const activeToplevel = () => mappedToplevels().find((toplevel) => toplevel.isActive()) ?? null;
|
|
13
|
+
const isWindowActivated = (window) => !canDisplayDeliverActivation(window) || window.isActive();
|
|
14
|
+
const isApplicationActivated = (window) => !canDisplayDeliverActivation(window) || activeToplevel() !== null;
|
|
15
|
+
const isTransientDescendant = (window, ancestor) => {
|
|
16
|
+
for (let parent = window.getTransientFor(); parent !== null; parent = parent.getTransientFor()) {
|
|
17
|
+
if (parent === ancestor) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return false;
|
|
22
|
+
};
|
|
23
|
+
const isModalGrabHeldOver = (modal, window) => modal.getModal() &&
|
|
24
|
+
modal !== window &&
|
|
25
|
+
modal.getGroup() === window.getGroup() &&
|
|
26
|
+
!isTransientDescendant(window, modal);
|
|
27
|
+
const isWindowBlockedByModal = (window) => mappedToplevels().some((toplevel) => isModalGrabHeldOver(toplevel, window));
|
|
28
|
+
const findPresentedWindowFailure = (window) => {
|
|
29
|
+
if (!isWindowAllocated(window)) {
|
|
30
|
+
return WINDOW_NOT_ALLOCATED;
|
|
31
|
+
}
|
|
32
|
+
return isWindowActivated(window) ? null : WINDOW_NOT_ACTIVATED;
|
|
33
|
+
};
|
|
34
|
+
const findRenderedWindowFailure = (window) => {
|
|
35
|
+
if (!isWindowAllocated(window)) {
|
|
36
|
+
return WINDOW_NOT_ALLOCATED;
|
|
37
|
+
}
|
|
38
|
+
return isApplicationActivated(window) ? null : NO_WINDOW_ACTIVATED;
|
|
39
|
+
};
|
|
40
|
+
export { activeToplevel, findPresentedWindowFailure, findRenderedWindowFailure, isWindowActivated, isWindowAllocated, isWindowBlockedByModal, mappedToplevels, };
|
|
41
|
+
//# sourceMappingURL=window-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"window-state.js","sourceRoot":"","sources":["../src/window-state.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Gtk from \"@gtkx/gi/gtk\";\n\nconst WINDOW_NOT_ALLOCATED = \"it was never allocated a size\";\nconst WINDOW_NOT_ACTIVATED = \"it never became active\";\nconst NO_WINDOW_ACTIVATED = \"no window of the application ever became active\";\n\nconst canDisplayDeliverActivation = (window: Gtk.Window): boolean => window.getDisplay().getDefaultSeat() !== null;\nconst isWindow = (widget: Gtk.Widget): widget is Gtk.Window => widget instanceof Gtk.Window;\n\nconst mappedToplevels = (): Gtk.Window[] =>\n Gtk.Window.listToplevels().filter((widget) => isWindow(widget)).filter((window) => window.getMapped());\n\nconst isWindowAllocated = (window: Gtk.Window): boolean => {\n const [isComputed, allocation] = window.computeBounds(window);\n\n return isComputed && allocation.getWidth() > 0;\n};\n\nconst activeToplevel = (): Gtk.Window | null => mappedToplevels().find((toplevel) => toplevel.isActive()) ?? null;\n\nconst isWindowActivated = (window: Gtk.Window): boolean =>\n !canDisplayDeliverActivation(window) || window.isActive();\n\nconst isApplicationActivated = (window: Gtk.Window): boolean =>\n !canDisplayDeliverActivation(window) || activeToplevel() !== null;\n\nconst isTransientDescendant = (window: Gtk.Window, ancestor: Gtk.Window): boolean => {\n for (let parent = window.getTransientFor(); parent !== null; parent = parent.getTransientFor()) {\n if (parent === ancestor) {\n return true;\n }\n }\n\n return false;\n};\n\nconst isModalGrabHeldOver = (modal: Gtk.Window, window: Gtk.Window): boolean =>\n modal.getModal() &&\n modal !== window &&\n modal.getGroup() === window.getGroup() &&\n !isTransientDescendant(window, modal);\n\nconst isWindowBlockedByModal = (window: Gtk.Window): boolean =>\n mappedToplevels().some((toplevel) => isModalGrabHeldOver(toplevel, window));\n\nconst findPresentedWindowFailure = (window: Gtk.Window): string | null => {\n if (!isWindowAllocated(window)) {\n return WINDOW_NOT_ALLOCATED;\n }\n\n return isWindowActivated(window) ? null : WINDOW_NOT_ACTIVATED;\n};\n\nconst findRenderedWindowFailure = (window: Gtk.Window): string | null => {\n if (!isWindowAllocated(window)) {\n return WINDOW_NOT_ALLOCATED;\n }\n\n return isApplicationActivated(window) ? null : NO_WINDOW_ACTIVATED;\n};\n\nexport {\n activeToplevel,\n findPresentedWindowFailure,\n findRenderedWindowFailure,\n isWindowActivated,\n isWindowAllocated,\n isWindowBlockedByModal,\n mappedToplevels,\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gtkx/testing",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Testing Library-style queries, user events, and screenshots for GTK4 widget trees rendered by GTKX",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"gtkx",
|
|
@@ -44,15 +44,25 @@
|
|
|
44
44
|
"dist",
|
|
45
45
|
"src"
|
|
46
46
|
],
|
|
47
|
+
"nx": {
|
|
48
|
+
"targets": {
|
|
49
|
+
"lint": {
|
|
50
|
+
"options": {
|
|
51
|
+
"cwd": ".",
|
|
52
|
+
"command": "eslint {projectRoot}"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
},
|
|
47
57
|
"engines": {
|
|
48
58
|
"node": ">=24"
|
|
49
59
|
},
|
|
50
60
|
"dependencies": {
|
|
51
61
|
"@vitest/expect": "^4.1.10",
|
|
52
62
|
"@vitest/pretty-format": "^4.1.10",
|
|
53
|
-
"@gtkx/
|
|
54
|
-
"@gtkx/
|
|
55
|
-
"@gtkx/
|
|
63
|
+
"@gtkx/runtime": "1.2.0",
|
|
64
|
+
"@gtkx/react": "1.2.0",
|
|
65
|
+
"@gtkx/utils": "1.2.0"
|
|
56
66
|
},
|
|
57
67
|
"peerDependencies": {
|
|
58
68
|
"@types/react": "^19.2",
|
|
@@ -60,9 +70,7 @@
|
|
|
60
70
|
},
|
|
61
71
|
"devDependencies": {
|
|
62
72
|
"@types/react": "^19.2.18",
|
|
63
|
-
"
|
|
64
|
-
"@gtkx/config": "1.0.0",
|
|
65
|
-
"@gtkx/vitest": "1.0.0"
|
|
73
|
+
"@gtkx/config": "1.2.0"
|
|
66
74
|
},
|
|
67
75
|
"scripts": {
|
|
68
76
|
"release": "tsx ../../scripts/release-package.ts"
|
package/src/act.ts
CHANGED
package/src/build-queries.ts
CHANGED
|
@@ -187,7 +187,7 @@ const requireSingle =
|
|
|
187
187
|
* @param queryAllBy Finds every widget the family matches.
|
|
188
188
|
* @param getMultipleError Builds the error thrown when a single-match variant finds more than one widget.
|
|
189
189
|
* @param getMissingError Builds the error thrown when a required match is missing.
|
|
190
|
-
* @returns The
|
|
190
|
+
* @returns The variants, in the order `[queryBy, getAllBy, getBy, findAllBy, findBy]`.
|
|
191
191
|
*/
|
|
192
192
|
const buildQueries = <Args extends unknown[]>(
|
|
193
193
|
queryAllBy: QueryAllBy<Args>,
|
package/src/config.ts
CHANGED
|
@@ -15,8 +15,16 @@ type Config = {
|
|
|
15
15
|
/** Default timeout in milliseconds for async utilities such as waitFor. */
|
|
16
16
|
asyncUtilTimeout: number;
|
|
17
17
|
|
|
18
|
-
/** Timeout in milliseconds
|
|
18
|
+
/** Timeout in milliseconds a user event waits for its widget to become actionable. */
|
|
19
19
|
actionabilityTimeout: number;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Timeout in milliseconds `render` waits for the window it shows the tree in to be laid out and
|
|
23
|
+
* activated. A window becoming active is a round trip through the compositor rather than an
|
|
24
|
+
* in-process check, so this is far longer than {@link Config.actionabilityTimeout}: it bounds
|
|
25
|
+
* how long a window that never activates takes to report, and costs nothing when one does.
|
|
26
|
+
*/
|
|
27
|
+
windowActivationTimeout: number;
|
|
20
28
|
};
|
|
21
29
|
|
|
22
30
|
/**
|
|
@@ -30,6 +38,7 @@ const defaultConfig: Config = {
|
|
|
30
38
|
getElementError: defaultGetElementError,
|
|
31
39
|
asyncUtilTimeout: 1000,
|
|
32
40
|
actionabilityTimeout: 500,
|
|
41
|
+
windowActivationTimeout: 5000,
|
|
33
42
|
};
|
|
34
43
|
|
|
35
44
|
const currentConfig: Config = { ...defaultConfig };
|