@gtkx/testing 0.11.0 → 0.12.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.
@@ -0,0 +1,13 @@
1
+ import type { Container } from "./traversal.js";
2
+ import type { BoundQueries } from "./types.js";
3
+ type ContainerOrGetter = Container | (() => Container);
4
+ /**
5
+ * Binds all query functions to a container.
6
+ *
7
+ * @param containerOrGetter - The container to bind queries to, or a function that returns it
8
+ * @returns Object with all query methods bound to the container
9
+ *
10
+ * @internal
11
+ */
12
+ export declare const bindQueries: (containerOrGetter: ContainerOrGetter) => BoundQueries;
13
+ export {};
@@ -0,0 +1,28 @@
1
+ import * as queries from "./queries.js";
2
+ const resolveContainer = (containerOrGetter) => typeof containerOrGetter === "function" ? containerOrGetter() : containerOrGetter;
3
+ /**
4
+ * Binds all query functions to a container.
5
+ *
6
+ * @param containerOrGetter - The container to bind queries to, or a function that returns it
7
+ * @returns Object with all query methods bound to the container
8
+ *
9
+ * @internal
10
+ */
11
+ export const bindQueries = (containerOrGetter) => ({
12
+ queryByRole: (role, options) => queries.queryByRole(resolveContainer(containerOrGetter), role, options),
13
+ queryByLabelText: (text, options) => queries.queryByLabelText(resolveContainer(containerOrGetter), text, options),
14
+ queryByText: (text, options) => queries.queryByText(resolveContainer(containerOrGetter), text, options),
15
+ queryByTestId: (testId, options) => queries.queryByTestId(resolveContainer(containerOrGetter), testId, options),
16
+ queryAllByRole: (role, options) => queries.queryAllByRole(resolveContainer(containerOrGetter), role, options),
17
+ queryAllByLabelText: (text, options) => queries.queryAllByLabelText(resolveContainer(containerOrGetter), text, options),
18
+ queryAllByText: (text, options) => queries.queryAllByText(resolveContainer(containerOrGetter), text, options),
19
+ queryAllByTestId: (testId, options) => queries.queryAllByTestId(resolveContainer(containerOrGetter), testId, options),
20
+ findByRole: (role, options) => queries.findByRole(resolveContainer(containerOrGetter), role, options),
21
+ findByLabelText: (text, options) => queries.findByLabelText(resolveContainer(containerOrGetter), text, options),
22
+ findByText: (text, options) => queries.findByText(resolveContainer(containerOrGetter), text, options),
23
+ findByTestId: (testId, options) => queries.findByTestId(resolveContainer(containerOrGetter), testId, options),
24
+ findAllByRole: (role, options) => queries.findAllByRole(resolveContainer(containerOrGetter), role, options),
25
+ findAllByLabelText: (text, options) => queries.findAllByLabelText(resolveContainer(containerOrGetter), text, options),
26
+ findAllByText: (text, options) => queries.findAllByText(resolveContainer(containerOrGetter), text, options),
27
+ findAllByTestId: (testId, options) => queries.findAllByTestId(resolveContainer(containerOrGetter), testId, options),
28
+ });
@@ -0,0 +1,59 @@
1
+ import type { Container } from "./traversal.js";
2
+ /**
3
+ * Configuration options for the testing library.
4
+ */
5
+ export type Config = {
6
+ /**
7
+ * Whether to show role suggestions in error messages when elements are not found.
8
+ * @default true
9
+ */
10
+ showSuggestions: boolean;
11
+ /**
12
+ * Custom error factory for query failures.
13
+ * Allows customizing how errors are constructed.
14
+ */
15
+ getElementError: (message: string, container: Container) => Error;
16
+ };
17
+ /**
18
+ * Returns the current testing library configuration.
19
+ *
20
+ * @returns The current configuration object
21
+ *
22
+ * @example
23
+ * ```tsx
24
+ * import { getConfig } from "@gtkx/testing";
25
+ *
26
+ * const config = getConfig();
27
+ * console.log(config.showSuggestions);
28
+ * ```
29
+ */
30
+ export declare const getConfig: () => Readonly<Config>;
31
+ /**
32
+ * Configures the testing library behavior.
33
+ *
34
+ * Accepts either a partial configuration object or a function that receives
35
+ * the current configuration and returns updates.
36
+ *
37
+ * @param newConfig - Partial configuration or updater function
38
+ *
39
+ * @example
40
+ * ```tsx
41
+ * import { configure } from "@gtkx/testing";
42
+ *
43
+ * // Disable role suggestions
44
+ * configure({ showSuggestions: false });
45
+ *
46
+ * // Use updater function
47
+ * configure((current) => ({
48
+ * showSuggestions: !current.showSuggestions,
49
+ * }));
50
+ * ```
51
+ */
52
+ export declare const configure: (newConfig: Partial<Config> | ((current: Config) => Partial<Config>)) => void;
53
+ /**
54
+ * Resets configuration to defaults.
55
+ * Primarily used for testing.
56
+ *
57
+ * @internal
58
+ */
59
+ export declare const resetConfig: () => void;
package/dist/config.js ADDED
@@ -0,0 +1,58 @@
1
+ const defaultGetElementError = (message, _container) => {
2
+ return new Error(message);
3
+ };
4
+ const defaultConfig = {
5
+ showSuggestions: true,
6
+ getElementError: defaultGetElementError,
7
+ };
8
+ let currentConfig = { ...defaultConfig };
9
+ /**
10
+ * Returns the current testing library configuration.
11
+ *
12
+ * @returns The current configuration object
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * import { getConfig } from "@gtkx/testing";
17
+ *
18
+ * const config = getConfig();
19
+ * console.log(config.showSuggestions);
20
+ * ```
21
+ */
22
+ export const getConfig = () => {
23
+ return currentConfig;
24
+ };
25
+ /**
26
+ * Configures the testing library behavior.
27
+ *
28
+ * Accepts either a partial configuration object or a function that receives
29
+ * the current configuration and returns updates.
30
+ *
31
+ * @param newConfig - Partial configuration or updater function
32
+ *
33
+ * @example
34
+ * ```tsx
35
+ * import { configure } from "@gtkx/testing";
36
+ *
37
+ * // Disable role suggestions
38
+ * configure({ showSuggestions: false });
39
+ *
40
+ * // Use updater function
41
+ * configure((current) => ({
42
+ * showSuggestions: !current.showSuggestions,
43
+ * }));
44
+ * ```
45
+ */
46
+ export const configure = (newConfig) => {
47
+ const updates = typeof newConfig === "function" ? newConfig(currentConfig) : newConfig;
48
+ currentConfig = { ...currentConfig, ...updates };
49
+ };
50
+ /**
51
+ * Resets configuration to defaults.
52
+ * Primarily used for testing.
53
+ *
54
+ * @internal
55
+ */
56
+ export const resetConfig = () => {
57
+ currentConfig = { ...defaultConfig };
58
+ };
@@ -0,0 +1,27 @@
1
+ import type * as Gtk from "@gtkx/ffi/gtk";
2
+ import type { Container } from "./traversal.js";
3
+ import type { ByRoleOptions, TextMatch } from "./types.js";
4
+ type QueryType = "role" | "text" | "labelText" | "testId";
5
+ /**
6
+ * Builds an error for when no elements match a query.
7
+ */
8
+ export declare const buildNotFoundError: (container: Container, queryType: QueryType, args: {
9
+ role?: Gtk.AccessibleRole;
10
+ text?: TextMatch;
11
+ testId?: TextMatch;
12
+ options?: ByRoleOptions;
13
+ }) => Error;
14
+ /**
15
+ * Builds an error for when multiple elements match a query but only one was expected.
16
+ */
17
+ export declare const buildMultipleFoundError: (container: Container, queryType: QueryType, args: {
18
+ role?: Gtk.AccessibleRole;
19
+ text?: TextMatch;
20
+ testId?: TextMatch;
21
+ options?: ByRoleOptions;
22
+ }, count: number) => Error;
23
+ /**
24
+ * Builds a timeout error with the last query error message.
25
+ */
26
+ export declare const buildTimeoutError: (timeout: number, lastError: Error | null) => Error;
27
+ export {};
@@ -0,0 +1,80 @@
1
+ import { getConfig } from "./config.js";
2
+ import { prettyWidget } from "./pretty-widget.js";
3
+ import { formatRole, prettyRoles } from "./role-helpers.js";
4
+ const formatTextMatcher = (text) => {
5
+ if (typeof text === "function") {
6
+ return "custom function";
7
+ }
8
+ if (text instanceof RegExp) {
9
+ return text.toString();
10
+ }
11
+ return `'${text}'`;
12
+ };
13
+ const formatByRoleDescription = (role, options) => {
14
+ const parts = [`role '${formatRole(role).toUpperCase()}'`];
15
+ if (options?.name)
16
+ parts.push(`name ${formatTextMatcher(options.name)}`);
17
+ if (options?.checked !== undefined)
18
+ parts.push(`checked=${options.checked}`);
19
+ if (options?.pressed !== undefined)
20
+ parts.push(`pressed=${options.pressed}`);
21
+ if (options?.selected !== undefined)
22
+ parts.push(`selected=${options.selected}`);
23
+ if (options?.expanded !== undefined)
24
+ parts.push(`expanded=${options.expanded}`);
25
+ if (options?.level !== undefined)
26
+ parts.push(`level=${options.level}`);
27
+ return parts.join(" and ");
28
+ };
29
+ const formatQueryDescription = (queryType, args) => {
30
+ switch (queryType) {
31
+ case "role":
32
+ return formatByRoleDescription(args.role, args.options);
33
+ case "text":
34
+ return `text ${formatTextMatcher(args.text)}`;
35
+ case "labelText":
36
+ return `label text ${formatTextMatcher(args.text)}`;
37
+ case "testId":
38
+ return `test id ${formatTextMatcher(args.testId)}`;
39
+ }
40
+ };
41
+ /**
42
+ * Builds an error for when no elements match a query.
43
+ */
44
+ export const buildNotFoundError = (container, queryType, args) => {
45
+ const config = getConfig();
46
+ const description = formatQueryDescription(queryType, args);
47
+ const lines = [`Unable to find an element with ${description}`];
48
+ if (config.showSuggestions && queryType === "role") {
49
+ lines.push("");
50
+ lines.push("Here are the accessible roles:");
51
+ lines.push("");
52
+ lines.push(prettyRoles(container));
53
+ }
54
+ lines.push("");
55
+ lines.push(prettyWidget(container, { highlight: false }));
56
+ const message = lines.join("\n");
57
+ return config.getElementError(message, container);
58
+ };
59
+ /**
60
+ * Builds an error for when multiple elements match a query but only one was expected.
61
+ */
62
+ export const buildMultipleFoundError = (container, queryType, args, count) => {
63
+ const config = getConfig();
64
+ const description = formatQueryDescription(queryType, args);
65
+ const lines = [`Found ${count} elements with ${description}, but expected only one`];
66
+ lines.push("");
67
+ lines.push(prettyWidget(container, { highlight: false }));
68
+ const message = lines.join("\n");
69
+ return config.getElementError(message, container);
70
+ };
71
+ /**
72
+ * Builds a timeout error with the last query error message.
73
+ */
74
+ export const buildTimeoutError = (timeout, lastError) => {
75
+ const baseMessage = `Timed out after ${timeout}ms`;
76
+ if (lastError) {
77
+ return new Error(`${baseMessage}.\n\n${lastError.message}`);
78
+ }
79
+ return new Error(baseMessage);
80
+ };
@@ -22,8 +22,8 @@ import { tick } from "./timing.js";
22
22
  */
23
23
  export const fireEvent = async (element, signalName, ...args) => {
24
24
  call("libgobject-2.0.so.0", "g_signal_emit_by_name", [
25
- { type: { type: "gobject", ownership: "none" }, value: element.id },
26
- { type: { type: "string", ownership: "none" }, value: signalName },
25
+ { type: { type: "gobject", ownership: "borrowed" }, value: element.handle },
26
+ { type: { type: "string", ownership: "borrowed" }, value: signalName },
27
27
  ...args,
28
28
  ], { type: "undefined" });
29
29
  await tick();
package/dist/index.d.ts CHANGED
@@ -1,10 +1,18 @@
1
+ export type { Config } from "./config.js";
2
+ export { configure, getConfig } from "./config.js";
1
3
  export { fireEvent } from "./fire-event.js";
2
- export { findAllByLabelText, findAllByRole, findAllByTestId, findAllByText, findByLabelText, findByRole, findByTestId, findByText, } from "./queries.js";
4
+ export type { PrettyWidgetOptions } from "./pretty-widget.js";
5
+ export { prettyWidget } from "./pretty-widget.js";
6
+ export { findAllByLabelText, findAllByRole, findAllByTestId, findAllByText, findByLabelText, findByRole, findByTestId, findByText, queryAllByLabelText, queryAllByRole, queryAllByTestId, queryAllByText, queryByLabelText, queryByRole, queryByTestId, queryByText, } from "./queries.js";
3
7
  export { cleanup, render } from "./render.js";
8
+ export type { RoleInfo } from "./role-helpers.js";
9
+ export { getRoles, logRoles, prettyRoles } from "./role-helpers.js";
4
10
  export { screen } from "./screen.js";
11
+ export type { ScreenshotOptions } from "./screenshot.js";
12
+ export { screenshot } from "./screenshot.js";
5
13
  export { tick } from "./timing.js";
6
- export type { BoundQueries, ByRoleOptions, NormalizerOptions, RenderOptions, RenderResult, TextMatch, TextMatchFunction, TextMatchOptions, WaitForOptions, } from "./types.js";
7
- export type { TabOptions } from "./user-event.js";
14
+ export type { BoundQueries, ByRoleOptions, NormalizerOptions, RenderOptions, RenderResult, ScreenshotResult, TextMatch, TextMatchFunction, TextMatchOptions, WaitForOptions, } from "./types.js";
15
+ export type { PointerInput, TabOptions } from "./user-event.js";
8
16
  export { userEvent } from "./user-event.js";
9
17
  export { waitFor, waitForElementToBeRemoved } from "./wait-for.js";
10
18
  export { within } from "./within.js";
package/dist/index.js CHANGED
@@ -1,7 +1,11 @@
1
+ export { configure, getConfig } from "./config.js";
1
2
  export { fireEvent } from "./fire-event.js";
2
- export { findAllByLabelText, findAllByRole, findAllByTestId, findAllByText, findByLabelText, findByRole, findByTestId, findByText, } from "./queries.js";
3
+ export { prettyWidget } from "./pretty-widget.js";
4
+ export { findAllByLabelText, findAllByRole, findAllByTestId, findAllByText, findByLabelText, findByRole, findByTestId, findByText, queryAllByLabelText, queryAllByRole, queryAllByTestId, queryAllByText, queryByLabelText, queryByRole, queryByTestId, queryByText, } from "./queries.js";
3
5
  export { cleanup, render } from "./render.js";
6
+ export { getRoles, logRoles, prettyRoles } from "./role-helpers.js";
4
7
  export { screen } from "./screen.js";
8
+ export { screenshot } from "./screenshot.js";
5
9
  export { tick } from "./timing.js";
6
10
  export { userEvent } from "./user-event.js";
7
11
  export { waitFor, waitForElementToBeRemoved } from "./wait-for.js";
@@ -0,0 +1,36 @@
1
+ import { type Container } from "./traversal.js";
2
+ /**
3
+ * Options for {@link prettyWidget}.
4
+ */
5
+ export type PrettyWidgetOptions = {
6
+ /** Maximum output length before truncation (default: 7000) */
7
+ maxLength?: number;
8
+ /** Enable ANSI color highlighting (default: auto-detect) */
9
+ highlight?: boolean;
10
+ /** Include widget IDs for MCP/agentic interactions (default: false) */
11
+ includeIds?: boolean;
12
+ };
13
+ /**
14
+ * Formats a widget tree as a readable string for debugging.
15
+ *
16
+ * Renders the widget hierarchy in an HTML-like format with accessibility
17
+ * attributes like role, data-testid, and text content.
18
+ *
19
+ * @param container - The container widget or application to format
20
+ * @param options - Formatting options for length and highlighting
21
+ * @returns Formatted string representation of the widget tree
22
+ *
23
+ * @example
24
+ * ```tsx
25
+ * import { prettyWidget } from "@gtkx/testing";
26
+ *
27
+ * console.log(prettyWidget(application));
28
+ * // Output:
29
+ * // <GtkApplicationWindow role="window">
30
+ * // <GtkButton role="button">
31
+ * // Click me
32
+ * // </GtkButton>
33
+ * // </GtkApplicationWindow>
34
+ * ```
35
+ */
36
+ export declare const prettyWidget: (container: Container, options?: PrettyWidgetOptions) => string;
@@ -0,0 +1,150 @@
1
+ import { getNativeId } from "@gtkx/ffi";
2
+ import { formatRole } from "./role-helpers.js";
3
+ import { isApplication } from "./traversal.js";
4
+ import { getWidgetText } from "./widget-text.js";
5
+ const DEFAULT_MAX_LENGTH = 7000;
6
+ const INDENT = " ";
7
+ const shouldHighlight = () => {
8
+ if (typeof process === "undefined")
9
+ return false;
10
+ if (process.env.COLORS === "false" || process.env.NO_COLOR)
11
+ return false;
12
+ if (process.env.COLORS === "true" || process.env.FORCE_COLOR)
13
+ return true;
14
+ return process.stdout?.isTTY ?? false;
15
+ };
16
+ const ansi = {
17
+ cyan: "\x1b[36m",
18
+ yellow: "\x1b[33m",
19
+ green: "\x1b[32m",
20
+ reset: "\x1b[0m",
21
+ };
22
+ const createColors = (enabled) => {
23
+ if (!enabled) {
24
+ const identity = (s) => s;
25
+ return { tag: identity, attr: identity, value: identity, text: identity, reset: "" };
26
+ }
27
+ return {
28
+ tag: (s) => `${ansi.cyan}${s}${ansi.reset}`,
29
+ attr: (s) => `${ansi.yellow}${s}${ansi.reset}`,
30
+ value: (s) => `${ansi.green}${s}${ansi.reset}`,
31
+ text: (s) => s,
32
+ reset: ansi.reset,
33
+ };
34
+ };
35
+ const formatTagName = (widget) => {
36
+ return widget.constructor.name;
37
+ };
38
+ const escapeAttrValue = (value) => {
39
+ return value.replace(/"/g, "&quot;");
40
+ };
41
+ const formatAttributes = (widget, colors, includeIds) => {
42
+ const attrs = [];
43
+ if (includeIds) {
44
+ attrs.push(["id", String(getNativeId(widget.handle))]);
45
+ }
46
+ const name = widget.getName();
47
+ if (name) {
48
+ attrs.push(["data-testid", name]);
49
+ }
50
+ const role = widget.getAccessibleRole();
51
+ if (role !== undefined) {
52
+ attrs.push(["role", formatRole(role)]);
53
+ }
54
+ if (!widget.getSensitive()) {
55
+ attrs.push(["aria-disabled", "true"]);
56
+ }
57
+ if (!widget.getVisible()) {
58
+ attrs.push(["aria-hidden", "true"]);
59
+ }
60
+ if (attrs.length === 0)
61
+ return "";
62
+ return attrs
63
+ .sort(([a], [b]) => {
64
+ if (a === "id")
65
+ return -1;
66
+ if (b === "id")
67
+ return 1;
68
+ return a.localeCompare(b);
69
+ })
70
+ .map(([key, value]) => ` ${colors.attr(key)}=${colors.value(`"${escapeAttrValue(value)}"`)}`)
71
+ .join("");
72
+ };
73
+ const hasChildren = (widget) => {
74
+ return widget.getFirstChild() !== null;
75
+ };
76
+ const printWidget = (widget, colors, depth, includeIds) => {
77
+ const indent = INDENT.repeat(depth);
78
+ const tagName = formatTagName(widget);
79
+ const attributes = formatAttributes(widget, colors, includeIds);
80
+ const text = getWidgetText(widget);
81
+ const children = [];
82
+ let child = widget.getFirstChild();
83
+ while (child) {
84
+ children.push(printWidget(child, colors, depth + 1, includeIds));
85
+ child = child.getNextSibling();
86
+ }
87
+ const openTag = `${colors.tag("<")}${colors.tag(tagName)}${attributes}${colors.tag(">")}`;
88
+ if (!hasChildren(widget) && !text) {
89
+ return `${indent}${openTag}\n`;
90
+ }
91
+ const closeTag = `${colors.tag("</")}${colors.tag(tagName)}${colors.tag(">")}`;
92
+ if (text && !hasChildren(widget)) {
93
+ const textContent = colors.text(text);
94
+ return `${indent}${openTag}\n${indent}${INDENT}${textContent}\n${indent}${closeTag}\n`;
95
+ }
96
+ let result = `${indent}${openTag}\n`;
97
+ if (text) {
98
+ result += `${indent}${INDENT}${colors.text(text)}\n`;
99
+ }
100
+ for (const childOutput of children) {
101
+ result += childOutput;
102
+ }
103
+ result += `${indent}${closeTag}\n`;
104
+ return result;
105
+ };
106
+ const printContainer = (container, colors, includeIds) => {
107
+ if (isApplication(container)) {
108
+ const windows = container.getWindows();
109
+ return windows.map((window) => printWidget(window, colors, 0, includeIds)).join("");
110
+ }
111
+ return printWidget(container, colors, 0, includeIds);
112
+ };
113
+ /**
114
+ * Formats a widget tree as a readable string for debugging.
115
+ *
116
+ * Renders the widget hierarchy in an HTML-like format with accessibility
117
+ * attributes like role, data-testid, and text content.
118
+ *
119
+ * @param container - The container widget or application to format
120
+ * @param options - Formatting options for length and highlighting
121
+ * @returns Formatted string representation of the widget tree
122
+ *
123
+ * @example
124
+ * ```tsx
125
+ * import { prettyWidget } from "@gtkx/testing";
126
+ *
127
+ * console.log(prettyWidget(application));
128
+ * // Output:
129
+ * // <GtkApplicationWindow role="window">
130
+ * // <GtkButton role="button">
131
+ * // Click me
132
+ * // </GtkButton>
133
+ * // </GtkApplicationWindow>
134
+ * ```
135
+ */
136
+ export const prettyWidget = (container, options = {}) => {
137
+ const envLimit = process.env.DEBUG_PRINT_LIMIT ? Number(process.env.DEBUG_PRINT_LIMIT) : DEFAULT_MAX_LENGTH;
138
+ const maxLength = options.maxLength ?? envLimit;
139
+ const highlight = options.highlight ?? shouldHighlight();
140
+ const includeIds = options.includeIds ?? false;
141
+ if (maxLength === 0) {
142
+ return "";
143
+ }
144
+ const colors = createColors(highlight);
145
+ const output = printContainer(container, colors, includeIds);
146
+ if (output.length > maxLength) {
147
+ return `${output.slice(0, maxLength)}...`;
148
+ }
149
+ return output.trimEnd();
150
+ };
package/dist/queries.d.ts CHANGED
@@ -1,6 +1,82 @@
1
- import * as Gtk from "@gtkx/ffi/gtk";
1
+ import type * as Gtk from "@gtkx/ffi/gtk";
2
+ import { type Container } from "./traversal.js";
2
3
  import type { ByRoleOptions, TextMatch, TextMatchOptions } from "./types.js";
3
- type Container = Gtk.Application | Gtk.Widget;
4
+ /**
5
+ * Finds all elements matching a role without throwing.
6
+ *
7
+ * @param container - The container to search within
8
+ * @param role - The GTK accessible role to match
9
+ * @param options - Query options including name and state filters
10
+ * @returns Array of matching widgets (empty if none found)
11
+ */
12
+ export declare const queryAllByRole: (container: Container, role: Gtk.AccessibleRole, options?: ByRoleOptions) => Gtk.Widget[];
13
+ /**
14
+ * Finds a single element matching a role without throwing.
15
+ *
16
+ * @param container - The container to search within
17
+ * @param role - The GTK accessible role to match
18
+ * @param options - Query options including name and state filters
19
+ * @returns The matching widget or null if not found
20
+ * @throws Error if multiple elements match
21
+ */
22
+ export declare const queryByRole: (container: Container, role: Gtk.AccessibleRole, options?: ByRoleOptions) => Gtk.Widget | null;
23
+ /**
24
+ * Finds all elements matching label text without throwing.
25
+ *
26
+ * @param container - The container to search within
27
+ * @param text - Text to match (string, RegExp, or custom matcher)
28
+ * @param options - Query options including normalization
29
+ * @returns Array of matching widgets (empty if none found)
30
+ */
31
+ export declare const queryAllByLabelText: (container: Container, text: TextMatch, options?: TextMatchOptions) => Gtk.Widget[];
32
+ /**
33
+ * Finds a single element matching label text without throwing.
34
+ *
35
+ * @param container - The container to search within
36
+ * @param text - Text to match (string, RegExp, or custom matcher)
37
+ * @param options - Query options including normalization
38
+ * @returns The matching widget or null if not found
39
+ * @throws Error if multiple elements match
40
+ */
41
+ export declare const queryByLabelText: (container: Container, text: TextMatch, options?: TextMatchOptions) => Gtk.Widget | null;
42
+ /**
43
+ * Finds all elements matching text content without throwing.
44
+ *
45
+ * @param container - The container to search within
46
+ * @param text - Text to match (string, RegExp, or custom matcher)
47
+ * @param options - Query options including normalization
48
+ * @returns Array of matching widgets (empty if none found)
49
+ */
50
+ export declare const queryAllByText: (container: Container, text: TextMatch, options?: TextMatchOptions) => Gtk.Widget[];
51
+ /**
52
+ * Finds a single element matching text content without throwing.
53
+ *
54
+ * @param container - The container to search within
55
+ * @param text - Text to match (string, RegExp, or custom matcher)
56
+ * @param options - Query options including normalization
57
+ * @returns The matching widget or null if not found
58
+ * @throws Error if multiple elements match
59
+ */
60
+ export declare const queryByText: (container: Container, text: TextMatch, options?: TextMatchOptions) => Gtk.Widget | null;
61
+ /**
62
+ * Finds all elements matching a test ID without throwing.
63
+ *
64
+ * @param container - The container to search within
65
+ * @param testId - Test ID to match (string, RegExp, or custom matcher)
66
+ * @param options - Query options including normalization
67
+ * @returns Array of matching widgets (empty if none found)
68
+ */
69
+ export declare const queryAllByTestId: (container: Container, testId: TextMatch, options?: TextMatchOptions) => Gtk.Widget[];
70
+ /**
71
+ * Finds a single element matching a test ID without throwing.
72
+ *
73
+ * @param container - The container to search within
74
+ * @param testId - Test ID to match (string, RegExp, or custom matcher)
75
+ * @param options - Query options including normalization
76
+ * @returns The matching widget or null if not found
77
+ * @throws Error if multiple elements match
78
+ */
79
+ export declare const queryByTestId: (container: Container, testId: TextMatch, options?: TextMatchOptions) => Gtk.Widget | null;
4
80
  /**
5
81
  * Finds a single element by accessible role.
6
82
  *
@@ -100,4 +176,3 @@ export declare const findByTestId: (container: Container, testId: TextMatch, opt
100
176
  * @returns Promise resolving to array of matching widgets
101
177
  */
102
178
  export declare const findAllByTestId: (container: Container, testId: TextMatch, options?: TextMatchOptions) => Promise<Gtk.Widget[]>;
103
- export {};