@gtkx/testing 1.0.0-rc.1 → 1.0.0-rc.3
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/dist/act.d.ts +6 -6
- package/dist/act.d.ts.map +1 -1
- package/dist/act.js +34 -26
- package/dist/act.js.map +1 -1
- package/dist/bound-queries.d.ts +5 -5
- package/dist/bound-queries.d.ts.map +1 -1
- package/dist/bound-queries.js.map +1 -1
- package/dist/build-queries.d.ts +5 -5
- package/dist/build-queries.d.ts.map +1 -1
- package/dist/build-queries.js +21 -9
- package/dist/build-queries.js.map +1 -1
- package/dist/cleanup-registry.d.ts +4 -3
- package/dist/cleanup-registry.d.ts.map +1 -1
- package/dist/cleanup-registry.js +13 -3
- package/dist/cleanup-registry.js.map +1 -1
- package/dist/config.d.ts +5 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +11 -9
- package/dist/config.js.map +1 -1
- package/dist/editable.d.ts +6 -5
- package/dist/editable.d.ts.map +1 -1
- package/dist/editable.js +7 -5
- package/dist/editable.js.map +1 -1
- package/dist/errors.d.ts +7 -6
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +64 -48
- package/dist/errors.js.map +1 -1
- package/dist/fire-event.d.ts +2 -1
- package/dist/fire-event.d.ts.map +1 -1
- package/dist/fire-event.js +2 -1
- package/dist/fire-event.js.map +1 -1
- package/dist/frame-sync.d.ts +2 -1
- package/dist/frame-sync.d.ts.map +1 -1
- package/dist/frame-sync.js +28 -21
- package/dist/frame-sync.js.map +1 -1
- package/dist/index.d.ts +9 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/matchers.d.ts +99 -35
- package/dist/matchers.d.ts.map +1 -1
- package/dist/matchers.js +314 -63
- package/dist/matchers.js.map +1 -1
- package/dist/normalize.d.ts +10 -0
- package/dist/normalize.d.ts.map +1 -0
- package/dist/normalize.js +20 -0
- package/dist/normalize.js.map +1 -0
- package/dist/pretty-widget.d.ts +6 -4
- package/dist/pretty-widget.d.ts.map +1 -1
- package/dist/pretty-widget.js +64 -24
- package/dist/pretty-widget.js.map +1 -1
- package/dist/queries.d.ts +129 -90
- package/dist/queries.d.ts.map +1 -1
- package/dist/queries.js +235 -164
- package/dist/queries.js.map +1 -1
- package/dist/register-test-hooks.js +2 -1
- package/dist/register-test-hooks.js.map +1 -1
- package/dist/render-hook.d.ts +3 -2
- package/dist/render-hook.d.ts.map +1 -1
- package/dist/render-hook.js +2 -1
- package/dist/render-hook.js.map +1 -1
- package/dist/render.d.ts +3 -2
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +25 -19
- package/dist/render.js.map +1 -1
- package/dist/role-helpers.d.ts +6 -5
- package/dist/role-helpers.d.ts.map +1 -1
- package/dist/role-helpers.js +16 -12
- package/dist/role-helpers.js.map +1 -1
- package/dist/screen.d.ts +4 -3
- package/dist/screen.d.ts.map +1 -1
- package/dist/screen.js +13 -11
- package/dist/screen.js.map +1 -1
- package/dist/screenshot.d.ts +4 -3
- package/dist/screenshot.d.ts.map +1 -1
- package/dist/screenshot.js +43 -36
- package/dist/screenshot.js.map +1 -1
- package/dist/suggestions.d.ts +11 -6
- package/dist/suggestions.d.ts.map +1 -1
- package/dist/suggestions.js +10 -5
- package/dist/suggestions.js.map +1 -1
- package/dist/traversal.d.ts +7 -7
- package/dist/traversal.d.ts.map +1 -1
- package/dist/traversal.js +17 -11
- package/dist/traversal.js.map +1 -1
- package/dist/types.d.ts +65 -24
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/user-event/adjustment.d.ts +5 -3
- package/dist/user-event/adjustment.d.ts.map +1 -1
- package/dist/user-event/adjustment.js +6 -4
- package/dist/user-event/adjustment.js.map +1 -1
- package/dist/user-event/click.d.ts +6 -5
- package/dist/user-event/click.d.ts.map +1 -1
- package/dist/user-event/click.js +29 -21
- package/dist/user-event/click.js.map +1 -1
- package/dist/user-event/controller.d.ts +7 -5
- package/dist/user-event/controller.d.ts.map +1 -1
- package/dist/user-event/controller.js +16 -6
- package/dist/user-event/controller.js.map +1 -1
- package/dist/user-event/dispatch.d.ts +3 -3
- package/dist/user-event/dispatch.d.ts.map +1 -1
- package/dist/user-event/dispatch.js +3 -2
- package/dist/user-event/dispatch.js.map +1 -1
- package/dist/user-event/event-wrapper.d.ts +2 -1
- package/dist/user-event/event-wrapper.d.ts.map +1 -1
- package/dist/user-event/event-wrapper.js +27 -16
- package/dist/user-event/event-wrapper.js.map +1 -1
- package/dist/user-event/gesture.d.ts +18 -14
- package/dist/user-event/gesture.d.ts.map +1 -1
- package/dist/user-event/gesture.js +70 -37
- package/dist/user-event/gesture.js.map +1 -1
- package/dist/user-event/index.d.ts +17 -10
- package/dist/user-event/index.d.ts.map +1 -1
- package/dist/user-event/index.js +7 -3
- package/dist/user-event/index.js.map +1 -1
- package/dist/user-event/keyboard.d.ts +4 -3
- package/dist/user-event/keyboard.d.ts.map +1 -1
- package/dist/user-event/keyboard.js +89 -58
- package/dist/user-event/keyboard.js.map +1 -1
- package/dist/user-event/pointer.d.ts +7 -3
- package/dist/user-event/pointer.d.ts.map +1 -1
- package/dist/user-event/pointer.js +4 -1
- package/dist/user-event/pointer.js.map +1 -1
- package/dist/user-event/selection.d.ts +3 -2
- package/dist/user-event/selection.d.ts.map +1 -1
- package/dist/user-event/selection.js +26 -27
- package/dist/user-event/selection.js.map +1 -1
- package/dist/user-event/state.d.ts +3 -2
- package/dist/user-event/state.d.ts.map +1 -1
- package/dist/user-event/state.js +2 -1
- package/dist/user-event/state.js.map +1 -1
- package/dist/user-event/text.d.ts +8 -7
- package/dist/user-event/text.d.ts.map +1 -1
- package/dist/user-event/text.js +39 -33
- package/dist/user-event/text.js.map +1 -1
- package/dist/wait-for.d.ts +5 -5
- package/dist/wait-for.d.ts.map +1 -1
- package/dist/wait-for.js +45 -30
- package/dist/wait-for.js.map +1 -1
- package/dist/widget-accessible-properties.d.ts +36 -25
- package/dist/widget-accessible-properties.d.ts.map +1 -1
- package/dist/widget-accessible-properties.js +215 -68
- package/dist/widget-accessible-properties.js.map +1 -1
- package/dist/within.d.ts +2 -1
- package/dist/within.d.ts.map +1 -1
- package/dist/within.js +2 -1
- package/dist/within.js.map +1 -1
- package/package.json +11 -9
- package/src/act.ts +44 -35
- package/src/bound-queries.ts +6 -6
- package/src/build-queries.ts +84 -43
- package/src/cleanup-registry.ts +18 -5
- package/src/config.ts +16 -12
- package/src/editable.ts +13 -6
- package/src/errors.ts +106 -45
- package/src/fire-event.ts +3 -1
- package/src/frame-sync.ts +38 -21
- package/src/index.ts +13 -3
- package/src/matchers.ts +568 -114
- package/src/normalize.ts +28 -0
- package/src/pretty-widget.ts +114 -42
- package/src/queries.ts +418 -256
- package/src/register-test-hooks.ts +4 -1
- package/src/render-hook.tsx +10 -4
- package/src/render.tsx +59 -34
- package/src/role-helpers.ts +29 -16
- package/src/screen.ts +17 -12
- package/src/screenshot.ts +61 -38
- package/src/suggestions.ts +29 -10
- package/src/traversal.ts +35 -15
- package/src/types.ts +111 -32
- package/src/user-event/adjustment.ts +23 -10
- package/src/user-event/click.ts +49 -20
- package/src/user-event/controller.ts +41 -7
- package/src/user-event/dispatch.ts +4 -2
- package/src/user-event/event-wrapper.ts +42 -16
- package/src/user-event/gesture.ts +135 -50
- package/src/user-event/index.ts +19 -12
- package/src/user-event/keyboard.ts +147 -61
- package/src/user-event/pointer.ts +20 -8
- package/src/user-event/selection.ts +69 -32
- package/src/user-event/state.ts +4 -2
- package/src/user-event/text.ts +73 -38
- package/src/wait-for.ts +77 -36
- package/src/widget-accessible-properties.ts +385 -79
- package/src/within.ts +8 -5
package/src/normalize.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { NormalizerFn, NormalizerOptions } from "./types.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Builds the default text normalizer, which optionally trims surrounding whitespace and collapses
|
|
5
|
+
* runs of whitespace into single spaces.
|
|
6
|
+
* @param options Toggles for trimming and whitespace collapsing.
|
|
7
|
+
* @returns A function that normalizes a string for comparison against a matcher.
|
|
8
|
+
*/
|
|
9
|
+
const getDefaultNormalizer = ({
|
|
10
|
+
trim = true,
|
|
11
|
+
collapseWhitespace = true,
|
|
12
|
+
}: NormalizerOptions = {}): NormalizerFn => {
|
|
13
|
+
return (text: string): string => {
|
|
14
|
+
let result = text;
|
|
15
|
+
|
|
16
|
+
if (trim) {
|
|
17
|
+
result = result.trim();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (collapseWhitespace) {
|
|
21
|
+
result = result.replaceAll(/\s+/g, " ");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return result;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export { getDefaultNormalizer };
|
package/src/pretty-widget.ts
CHANGED
|
@@ -4,22 +4,43 @@ import { formatRole } from "./role-helpers.js";
|
|
|
4
4
|
import { type Container, roots } from "./traversal.js";
|
|
5
5
|
import { getWidgetNodeText } from "./widget-accessible-properties.js";
|
|
6
6
|
|
|
7
|
-
const DEFAULT_MAX_LENGTH = 7000;
|
|
8
|
-
const INDENT = " ";
|
|
9
|
-
|
|
10
7
|
type WidgetIdResolver = (widget: Gtk.Widget) => string;
|
|
11
8
|
|
|
12
9
|
/**
|
|
13
10
|
* Options controlling how a widget tree is rendered to a string by
|
|
14
11
|
* {@link prettyWidget} and {@link logWidget}.
|
|
15
12
|
*/
|
|
16
|
-
|
|
13
|
+
type PrettyWidgetOptions = {
|
|
17
14
|
/** Truncates the output once it exceeds this many characters. */
|
|
18
15
|
maxLength?: number;
|
|
19
16
|
/** Whether to apply ANSI color highlighting; defaults to the terminal capabilities. */
|
|
20
17
|
highlight?: boolean;
|
|
21
18
|
/** Resolves an `id` attribute to show for each widget. */
|
|
22
19
|
getId?: WidgetIdResolver;
|
|
20
|
+
/** Stops descending past this depth, replacing deeper children with a summary line. */
|
|
21
|
+
maxDepth?: number;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
type Colors = {
|
|
25
|
+
tag: (s: string) => string;
|
|
26
|
+
attr: (s: string) => string;
|
|
27
|
+
value: (s: string) => string;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
type FormatContext = {
|
|
31
|
+
getId: WidgetIdResolver | undefined;
|
|
32
|
+
colors: Colors;
|
|
33
|
+
maxDepth: number | undefined;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const DEFAULT_MAX_LENGTH = 7000;
|
|
37
|
+
const INDENT = " ";
|
|
38
|
+
|
|
39
|
+
const ansi = {
|
|
40
|
+
cyan: "\u{1B}[36m",
|
|
41
|
+
yellow: "\u{1B}[33m",
|
|
42
|
+
green: "\u{1B}[32m",
|
|
43
|
+
reset: "\u{1B}[0m",
|
|
23
44
|
};
|
|
24
45
|
|
|
25
46
|
const buildAttrs = (widget: Gtk.Widget, getId: WidgetIdResolver | undefined): [string, string][] => {
|
|
@@ -30,6 +51,7 @@ const buildAttrs = (widget: Gtk.Widget, getId: WidgetIdResolver | undefined): [s
|
|
|
30
51
|
}
|
|
31
52
|
|
|
32
53
|
const name = widget.getName();
|
|
54
|
+
|
|
33
55
|
if (name) {
|
|
34
56
|
attrs.push(["name", name]);
|
|
35
57
|
}
|
|
@@ -45,38 +67,38 @@ const buildAttrs = (widget: Gtk.Widget, getId: WidgetIdResolver | undefined): [s
|
|
|
45
67
|
}
|
|
46
68
|
|
|
47
69
|
const idAttrs = attrs.filter(([key]) => key === "id");
|
|
70
|
+
|
|
48
71
|
const otherAttrs = sortStringsBy(
|
|
49
72
|
attrs.filter(([key]) => key !== "id"),
|
|
50
73
|
([key]) => key,
|
|
51
74
|
);
|
|
75
|
+
|
|
52
76
|
return [...idAttrs, ...otherAttrs];
|
|
53
77
|
};
|
|
54
78
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
};
|
|
79
|
+
const shouldHighlight = (): boolean => {
|
|
80
|
+
if (typeof process === "undefined") {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
60
83
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
84
|
+
if (process.env.COLORS === "false" || process.env.NO_COLOR) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (process.env.COLORS === "true" || process.env.FORCE_COLOR) {
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
67
91
|
|
|
68
|
-
const shouldHighlight = (): boolean => {
|
|
69
|
-
if (typeof process === "undefined") return false;
|
|
70
|
-
if (process.env.COLORS === "false" || process.env.NO_COLOR) return false;
|
|
71
|
-
if (process.env.COLORS === "true" || process.env.FORCE_COLOR) return true;
|
|
72
92
|
return process.stdout.isTTY;
|
|
73
93
|
};
|
|
74
94
|
|
|
75
|
-
const createColors = (
|
|
76
|
-
if (!
|
|
95
|
+
const createColors = (isEnabled: boolean): Colors => {
|
|
96
|
+
if (!isEnabled) {
|
|
77
97
|
const identity = (s: string): string => s;
|
|
98
|
+
|
|
78
99
|
return { tag: identity, attr: identity, value: identity };
|
|
79
100
|
}
|
|
101
|
+
|
|
80
102
|
return {
|
|
81
103
|
tag: (s) => `${ansi.cyan}${s}${ansi.reset}`,
|
|
82
104
|
attr: (s) => `${ansi.yellow}${s}${ansi.reset}`,
|
|
@@ -86,21 +108,57 @@ const createColors = (enabled: boolean): Colors => {
|
|
|
86
108
|
|
|
87
109
|
const escapeAttrValue = (value: string): string => value.replaceAll('"', """);
|
|
88
110
|
|
|
111
|
+
const formatAttr = (key: string, value: string, colors: Colors): string => {
|
|
112
|
+
const quoted = `"${escapeAttrValue(value)}"`;
|
|
113
|
+
|
|
114
|
+
return ` ${colors.attr(key)}=${colors.value(quoted)}`;
|
|
115
|
+
};
|
|
116
|
+
|
|
89
117
|
const formatAttrs = (attrs: [string, string][], colors: Colors): string =>
|
|
90
|
-
attrs.map(([key, value]) =>
|
|
91
|
-
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
118
|
+
attrs.map(([key, value]) => formatAttr(key, value, colors)).join("");
|
|
119
|
+
|
|
120
|
+
const countChildren = (widget: Gtk.Widget): number => {
|
|
121
|
+
let count = 0;
|
|
122
|
+
let child = widget.getFirstChild();
|
|
123
|
+
|
|
124
|
+
while (child) {
|
|
125
|
+
count += 1;
|
|
126
|
+
child = child.getNextSibling();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return count;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const formatHiddenChildrenLine = (widget: Gtk.Widget, depth: number, ctx: FormatContext): string => {
|
|
133
|
+
const { getId, colors } = ctx;
|
|
134
|
+
const indent = INDENT.repeat(depth);
|
|
135
|
+
const count = countChildren(widget);
|
|
136
|
+
const hint = getId ? ` (pass rootId="${getId(widget)}" or raise maxDepth to expand)` : "";
|
|
137
|
+
const plural = count === 1 ? "" : "s";
|
|
138
|
+
const summary = `… ${String(count)} child widget${plural} hidden${hint}`;
|
|
139
|
+
|
|
140
|
+
return `${indent}${INDENT}${colors.tag(summary)}\n`;
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const formatChildren = (widget: Gtk.Widget, depth: number, ctx: FormatContext): string => {
|
|
144
|
+
let output = "";
|
|
145
|
+
let child = widget.getFirstChild();
|
|
146
|
+
|
|
147
|
+
while (child) {
|
|
148
|
+
output += formatWidget(child, depth + 1, ctx);
|
|
149
|
+
child = child.getNextSibling();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return output;
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const formatWidget = (widget: Gtk.Widget, depth: number, ctx: FormatContext): string => {
|
|
156
|
+
const { getId, colors, maxDepth } = ctx;
|
|
98
157
|
const indent = INDENT.repeat(depth);
|
|
99
158
|
const tag = widget.constructor.name;
|
|
100
159
|
const attrs = formatAttrs(buildAttrs(widget, getId), colors);
|
|
101
160
|
const openTag = `${colors.tag("<")}${colors.tag(tag)}${attrs}${colors.tag(">")}`;
|
|
102
161
|
const closeTag = `${colors.tag("</")}${colors.tag(tag)}${colors.tag(">")}`;
|
|
103
|
-
|
|
104
162
|
const text = getWidgetNodeText(widget);
|
|
105
163
|
const firstChild = widget.getFirstChild();
|
|
106
164
|
|
|
@@ -109,18 +167,30 @@ const formatWidget = (
|
|
|
109
167
|
}
|
|
110
168
|
|
|
111
169
|
let output = `${indent}${openTag}\n`;
|
|
170
|
+
|
|
112
171
|
if (text) {
|
|
113
172
|
output += `${indent}${INDENT}${text}\n`;
|
|
114
173
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
output +=
|
|
118
|
-
|
|
174
|
+
|
|
175
|
+
if (firstChild && maxDepth !== undefined && depth >= maxDepth) {
|
|
176
|
+
output += formatHiddenChildrenLine(widget, depth, ctx);
|
|
177
|
+
output += `${indent}${closeTag}\n`;
|
|
178
|
+
|
|
179
|
+
return output;
|
|
119
180
|
}
|
|
181
|
+
|
|
182
|
+
output += formatChildren(widget, depth, ctx);
|
|
120
183
|
output += `${indent}${closeTag}\n`;
|
|
184
|
+
|
|
121
185
|
return output;
|
|
122
186
|
};
|
|
123
187
|
|
|
188
|
+
const resolveMaxLength = (options: PrettyWidgetOptions): number => {
|
|
189
|
+
const envLimit = process.env.DEBUG_PRINT_LIMIT ? Number(process.env.DEBUG_PRINT_LIMIT) : DEFAULT_MAX_LENGTH;
|
|
190
|
+
|
|
191
|
+
return options.maxLength ?? envLimit;
|
|
192
|
+
};
|
|
193
|
+
|
|
124
194
|
/**
|
|
125
195
|
* Renders a widget tree as an indented, HTML-like string showing each widget's
|
|
126
196
|
* tag, accessible attributes, and text content.
|
|
@@ -129,20 +199,19 @@ const formatWidget = (
|
|
|
129
199
|
* @param options Formatting options such as truncation length and highlighting.
|
|
130
200
|
* @returns The formatted representation of the tree.
|
|
131
201
|
*/
|
|
132
|
-
|
|
133
|
-
const
|
|
134
|
-
const maxLength = options.maxLength ?? envLimit;
|
|
202
|
+
const prettyWidget = (container: Container, options: PrettyWidgetOptions = {}): string => {
|
|
203
|
+
const maxLength = resolveMaxLength(options);
|
|
135
204
|
|
|
136
205
|
if (maxLength === 0) {
|
|
137
206
|
return "";
|
|
138
207
|
}
|
|
139
208
|
|
|
140
|
-
const
|
|
141
|
-
const colors = createColors(
|
|
142
|
-
|
|
209
|
+
const isHighlight = options.highlight ?? shouldHighlight();
|
|
210
|
+
const colors = createColors(isHighlight);
|
|
143
211
|
let output = "";
|
|
212
|
+
|
|
144
213
|
for (const root of roots(container)) {
|
|
145
|
-
output += formatWidget(root, 0, options.getId, colors);
|
|
214
|
+
output += formatWidget(root, 0, { getId: options.getId, colors, maxDepth: options.maxDepth });
|
|
146
215
|
}
|
|
147
216
|
|
|
148
217
|
if (output.length > maxLength) {
|
|
@@ -158,9 +227,12 @@ export const prettyWidget = (container: Container, options: PrettyWidgetOptions
|
|
|
158
227
|
* @param container A single scope or an array of scopes to format and print.
|
|
159
228
|
* @param options Formatting options passed through to {@link prettyWidget}.
|
|
160
229
|
*/
|
|
161
|
-
|
|
230
|
+
const logWidget = (container: Container | Container[], options?: PrettyWidgetOptions): void => {
|
|
162
231
|
const containers: Container[] = Array.isArray(container) ? container : [container];
|
|
232
|
+
|
|
163
233
|
for (const target of containers) {
|
|
164
234
|
console.log(prettyWidget(target, options));
|
|
165
235
|
}
|
|
166
236
|
};
|
|
237
|
+
|
|
238
|
+
export { prettyWidget, logWidget, type PrettyWidgetOptions };
|