@gtkx/testing 0.9.3 → 0.10.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 +55 -67
- package/dist/fire-event.d.ts +14 -8
- package/dist/fire-event.js +14 -8
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/queries.d.ts +59 -24
- package/dist/queries.js +71 -38
- package/dist/render.d.ts +39 -10
- package/dist/render.js +63 -27
- package/dist/screen.d.ts +28 -3
- package/dist/screen.js +29 -4
- package/dist/timing.d.ts +16 -0
- package/dist/timing.js +16 -0
- package/dist/types.d.ts +55 -48
- package/dist/user-event.d.ts +79 -5
- package/dist/user-event.js +121 -20
- package/dist/wait-for.d.ts +30 -8
- package/dist/wait-for.js +31 -10
- package/dist/within.d.ts +18 -7
- package/dist/within.js +18 -7
- package/package.json +8 -4
package/dist/render.d.ts
CHANGED
|
@@ -1,19 +1,48 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
2
|
import type { RenderOptions, RenderResult } from "./types.js";
|
|
3
3
|
/**
|
|
4
|
-
* Renders a React element
|
|
4
|
+
* Renders a React element for testing.
|
|
5
|
+
*
|
|
6
|
+
* Creates a GTK application context and renders the element, returning
|
|
7
|
+
* query methods and utilities for interacting with the rendered widgets.
|
|
8
|
+
*
|
|
5
9
|
* @param element - The React element to render
|
|
6
|
-
* @param options - Render options including wrapper
|
|
7
|
-
* @returns
|
|
10
|
+
* @param options - Render options including wrapper configuration
|
|
11
|
+
* @returns A promise resolving to query methods and utilities
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* import { render, screen } from "@gtkx/testing";
|
|
16
|
+
*
|
|
17
|
+
* test("button click", async () => {
|
|
18
|
+
* await render(<MyButton />);
|
|
19
|
+
* const button = await screen.findByRole(Gtk.AccessibleRole.BUTTON);
|
|
20
|
+
* await userEvent.click(button);
|
|
21
|
+
* });
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @see {@link cleanup} for cleaning up after tests
|
|
25
|
+
* @see {@link screen} for global query access
|
|
8
26
|
*/
|
|
9
27
|
export declare const render: (element: ReactNode, options?: RenderOptions) => Promise<RenderResult>;
|
|
10
28
|
/**
|
|
11
|
-
* Cleans up the rendered component
|
|
12
|
-
*
|
|
29
|
+
* Cleans up the rendered component tree.
|
|
30
|
+
*
|
|
31
|
+
* Unmounts all rendered components and resets the testing environment.
|
|
32
|
+
* Call this in `afterEach` to ensure tests don't affect each other.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```tsx
|
|
36
|
+
* import { render, cleanup } from "@gtkx/testing";
|
|
37
|
+
*
|
|
38
|
+
* afterEach(async () => {
|
|
39
|
+
* await cleanup();
|
|
40
|
+
* });
|
|
41
|
+
*
|
|
42
|
+
* test("my test", async () => {
|
|
43
|
+
* await render(<MyComponent />);
|
|
44
|
+
* // ...
|
|
45
|
+
* });
|
|
46
|
+
* ```
|
|
13
47
|
*/
|
|
14
48
|
export declare const cleanup: () => Promise<void>;
|
|
15
|
-
/**
|
|
16
|
-
* Tears down the testing environment by cleaning up and stopping GTK.
|
|
17
|
-
* Can be used as global teardown in your test runner configuration.
|
|
18
|
-
*/
|
|
19
|
-
export declare const teardown: () => Promise<void>;
|
package/dist/render.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { discardAllBatches, getNativeObject, start } from "@gtkx/ffi";
|
|
3
3
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
4
|
-
import {
|
|
4
|
+
import { ApplicationContext, GtkApplicationWindow, reconciler } from "@gtkx/react";
|
|
5
5
|
import * as queries from "./queries.js";
|
|
6
6
|
import { setScreenRoot } from "./screen.js";
|
|
7
7
|
import { tick } from "./timing.js";
|
|
8
8
|
import { hasLabel } from "./widget.js";
|
|
9
|
-
|
|
9
|
+
let application = null;
|
|
10
10
|
let container = null;
|
|
11
|
+
let lastRenderError = null;
|
|
12
|
+
const APP_ID = `com.gtkx.test${process.pid}`;
|
|
11
13
|
const getWidgetLabel = (widget) => {
|
|
12
14
|
if (!hasLabel(widget))
|
|
13
15
|
return null;
|
|
@@ -35,18 +37,28 @@ const printWidgetTree = (root, indent = 0) => {
|
|
|
35
37
|
return result;
|
|
36
38
|
};
|
|
37
39
|
const update = async (instance, element, fiberRoot) => {
|
|
40
|
+
lastRenderError = null;
|
|
38
41
|
instance.updateContainer(element, fiberRoot, null, () => { });
|
|
39
42
|
await tick();
|
|
43
|
+
if (lastRenderError) {
|
|
44
|
+
const error = lastRenderError;
|
|
45
|
+
lastRenderError = null;
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
const handleError = (error) => {
|
|
50
|
+
discardAllBatches();
|
|
51
|
+
lastRenderError = error;
|
|
40
52
|
};
|
|
41
53
|
const ensureInitialized = () => {
|
|
42
|
-
|
|
54
|
+
application = start(APP_ID);
|
|
43
55
|
if (!container) {
|
|
44
56
|
const instance = reconciler.getInstance();
|
|
45
|
-
container = instance.createContainer(
|
|
57
|
+
container = instance.createContainer(application, 0, null, false, null, "", handleError, handleError, () => { }, () => { }, null);
|
|
46
58
|
}
|
|
47
|
-
return { app, container };
|
|
59
|
+
return { app: application, container };
|
|
48
60
|
};
|
|
49
|
-
const DefaultWrapper = ({ children }) => (_jsx(
|
|
61
|
+
const DefaultWrapper = ({ children }) => (_jsx(GtkApplicationWindow, { children: children }));
|
|
50
62
|
const wrapElement = (element, wrapper = true) => {
|
|
51
63
|
if (wrapper === false)
|
|
52
64
|
return element;
|
|
@@ -56,16 +68,35 @@ const wrapElement = (element, wrapper = true) => {
|
|
|
56
68
|
return _jsx(Wrapper, { children: element });
|
|
57
69
|
};
|
|
58
70
|
/**
|
|
59
|
-
* Renders a React element
|
|
71
|
+
* Renders a React element for testing.
|
|
72
|
+
*
|
|
73
|
+
* Creates a GTK application context and renders the element, returning
|
|
74
|
+
* query methods and utilities for interacting with the rendered widgets.
|
|
75
|
+
*
|
|
60
76
|
* @param element - The React element to render
|
|
61
|
-
* @param options - Render options including wrapper
|
|
62
|
-
* @returns
|
|
77
|
+
* @param options - Render options including wrapper configuration
|
|
78
|
+
* @returns A promise resolving to query methods and utilities
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```tsx
|
|
82
|
+
* import { render, screen } from "@gtkx/testing";
|
|
83
|
+
*
|
|
84
|
+
* test("button click", async () => {
|
|
85
|
+
* await render(<MyButton />);
|
|
86
|
+
* const button = await screen.findByRole(Gtk.AccessibleRole.BUTTON);
|
|
87
|
+
* await userEvent.click(button);
|
|
88
|
+
* });
|
|
89
|
+
* ```
|
|
90
|
+
*
|
|
91
|
+
* @see {@link cleanup} for cleaning up after tests
|
|
92
|
+
* @see {@link screen} for global query access
|
|
63
93
|
*/
|
|
64
94
|
export const render = async (element, options) => {
|
|
65
95
|
const { app: application, container: fiberRoot } = ensureInitialized();
|
|
66
96
|
const instance = reconciler.getInstance();
|
|
67
97
|
const wrappedElement = wrapElement(element, options?.wrapper);
|
|
68
|
-
|
|
98
|
+
const withContext = _jsx(ApplicationContext.Provider, { value: application, children: wrappedElement });
|
|
99
|
+
await update(instance, withContext, fiberRoot);
|
|
69
100
|
setScreenRoot(application);
|
|
70
101
|
return {
|
|
71
102
|
container: application,
|
|
@@ -80,7 +111,8 @@ export const render = async (element, options) => {
|
|
|
80
111
|
unmount: () => update(instance, null, fiberRoot),
|
|
81
112
|
rerender: (newElement) => {
|
|
82
113
|
const wrapped = wrapElement(newElement, options?.wrapper);
|
|
83
|
-
|
|
114
|
+
const withCtx = _jsx(ApplicationContext.Provider, { value: application, children: wrapped });
|
|
115
|
+
return update(instance, withCtx, fiberRoot);
|
|
84
116
|
},
|
|
85
117
|
debug: () => {
|
|
86
118
|
const activeWindow = application.getActiveWindow();
|
|
@@ -91,26 +123,30 @@ export const render = async (element, options) => {
|
|
|
91
123
|
};
|
|
92
124
|
};
|
|
93
125
|
/**
|
|
94
|
-
* Cleans up the rendered component
|
|
95
|
-
*
|
|
126
|
+
* Cleans up the rendered component tree.
|
|
127
|
+
*
|
|
128
|
+
* Unmounts all rendered components and resets the testing environment.
|
|
129
|
+
* Call this in `afterEach` to ensure tests don't affect each other.
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```tsx
|
|
133
|
+
* import { render, cleanup } from "@gtkx/testing";
|
|
134
|
+
*
|
|
135
|
+
* afterEach(async () => {
|
|
136
|
+
* await cleanup();
|
|
137
|
+
* });
|
|
138
|
+
*
|
|
139
|
+
* test("my test", async () => {
|
|
140
|
+
* await render(<MyComponent />);
|
|
141
|
+
* // ...
|
|
142
|
+
* });
|
|
143
|
+
* ```
|
|
96
144
|
*/
|
|
97
145
|
export const cleanup = async () => {
|
|
98
|
-
if (container) {
|
|
99
|
-
const app = getApplication();
|
|
146
|
+
if (container && application) {
|
|
100
147
|
const instance = reconciler.getInstance();
|
|
101
148
|
await update(instance, null, container);
|
|
102
|
-
for (const window of app.getWindows()) {
|
|
103
|
-
window.destroy();
|
|
104
|
-
}
|
|
105
149
|
}
|
|
106
150
|
container = null;
|
|
107
151
|
setScreenRoot(null);
|
|
108
152
|
};
|
|
109
|
-
/**
|
|
110
|
-
* Tears down the testing environment by cleaning up and stopping GTK.
|
|
111
|
-
* Can be used as global teardown in your test runner configuration.
|
|
112
|
-
*/
|
|
113
|
-
export const teardown = async () => {
|
|
114
|
-
await cleanup();
|
|
115
|
-
stop();
|
|
116
|
-
};
|
package/dist/screen.d.ts
CHANGED
|
@@ -1,19 +1,44 @@
|
|
|
1
1
|
import type * as Gtk from "@gtkx/ffi/gtk";
|
|
2
2
|
import type { ByRoleOptions, TextMatch, TextMatchOptions } from "./types.js";
|
|
3
|
+
/** @internal */
|
|
3
4
|
export declare const setScreenRoot: (root: Gtk.Application | null) => void;
|
|
4
5
|
/**
|
|
5
|
-
* Global
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* Global query object for accessing rendered components.
|
|
7
|
+
*
|
|
8
|
+
* Provides the same query methods as render result, but automatically
|
|
9
|
+
* uses the most recently rendered application as the container.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* import { render, screen } from "@gtkx/testing";
|
|
14
|
+
*
|
|
15
|
+
* test("finds button", async () => {
|
|
16
|
+
* await render(<MyComponent />);
|
|
17
|
+
* const button = await screen.findByRole(Gtk.AccessibleRole.BUTTON);
|
|
18
|
+
* expect(button).toBeDefined();
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @see {@link render} for rendering components
|
|
23
|
+
* @see {@link within} for scoped queries
|
|
8
24
|
*/
|
|
9
25
|
export declare const screen: {
|
|
26
|
+
/** Find single element by accessible role */
|
|
10
27
|
findByRole: (role: Gtk.AccessibleRole, options?: ByRoleOptions) => Promise<Gtk.Widget>;
|
|
28
|
+
/** Find single element by label/text content */
|
|
11
29
|
findByLabelText: (text: TextMatch, options?: TextMatchOptions) => Promise<Gtk.Widget>;
|
|
30
|
+
/** Find single element by visible text */
|
|
12
31
|
findByText: (text: TextMatch, options?: TextMatchOptions) => Promise<Gtk.Widget>;
|
|
32
|
+
/** Find single element by test ID (widget name) */
|
|
13
33
|
findByTestId: (testId: TextMatch, options?: TextMatchOptions) => Promise<Gtk.Widget>;
|
|
34
|
+
/** Find all elements by accessible role */
|
|
14
35
|
findAllByRole: (role: Gtk.AccessibleRole, options?: ByRoleOptions) => Promise<Gtk.Widget[]>;
|
|
36
|
+
/** Find all elements by label/text content */
|
|
15
37
|
findAllByLabelText: (text: TextMatch, options?: TextMatchOptions) => Promise<Gtk.Widget[]>;
|
|
38
|
+
/** Find all elements by visible text */
|
|
16
39
|
findAllByText: (text: TextMatch, options?: TextMatchOptions) => Promise<Gtk.Widget[]>;
|
|
40
|
+
/** Find all elements by test ID (widget name) */
|
|
17
41
|
findAllByTestId: (testId: TextMatch, options?: TextMatchOptions) => Promise<Gtk.Widget[]>;
|
|
42
|
+
/** Print debug info to console */
|
|
18
43
|
debug: () => void;
|
|
19
44
|
};
|
package/dist/screen.js
CHANGED
|
@@ -1,28 +1,53 @@
|
|
|
1
1
|
import * as queries from "./queries.js";
|
|
2
2
|
let currentRoot = null;
|
|
3
|
+
/** @internal */
|
|
3
4
|
export const setScreenRoot = (root) => {
|
|
4
5
|
currentRoot = root;
|
|
5
6
|
};
|
|
6
7
|
const getRoot = () => {
|
|
7
8
|
if (!currentRoot) {
|
|
8
|
-
throw new Error("No render has been performed
|
|
9
|
+
throw new Error("No render has been performed: call render() before using screen queries");
|
|
9
10
|
}
|
|
10
11
|
return currentRoot;
|
|
11
12
|
};
|
|
12
13
|
/**
|
|
13
|
-
* Global
|
|
14
|
-
*
|
|
15
|
-
*
|
|
14
|
+
* Global query object for accessing rendered components.
|
|
15
|
+
*
|
|
16
|
+
* Provides the same query methods as render result, but automatically
|
|
17
|
+
* uses the most recently rendered application as the container.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```tsx
|
|
21
|
+
* import { render, screen } from "@gtkx/testing";
|
|
22
|
+
*
|
|
23
|
+
* test("finds button", async () => {
|
|
24
|
+
* await render(<MyComponent />);
|
|
25
|
+
* const button = await screen.findByRole(Gtk.AccessibleRole.BUTTON);
|
|
26
|
+
* expect(button).toBeDefined();
|
|
27
|
+
* });
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @see {@link render} for rendering components
|
|
31
|
+
* @see {@link within} for scoped queries
|
|
16
32
|
*/
|
|
17
33
|
export const screen = {
|
|
34
|
+
/** Find single element by accessible role */
|
|
18
35
|
findByRole: (role, options) => queries.findByRole(getRoot(), role, options),
|
|
36
|
+
/** Find single element by label/text content */
|
|
19
37
|
findByLabelText: (text, options) => queries.findByLabelText(getRoot(), text, options),
|
|
38
|
+
/** Find single element by visible text */
|
|
20
39
|
findByText: (text, options) => queries.findByText(getRoot(), text, options),
|
|
40
|
+
/** Find single element by test ID (widget name) */
|
|
21
41
|
findByTestId: (testId, options) => queries.findByTestId(getRoot(), testId, options),
|
|
42
|
+
/** Find all elements by accessible role */
|
|
22
43
|
findAllByRole: (role, options) => queries.findAllByRole(getRoot(), role, options),
|
|
44
|
+
/** Find all elements by label/text content */
|
|
23
45
|
findAllByLabelText: (text, options) => queries.findAllByLabelText(getRoot(), text, options),
|
|
46
|
+
/** Find all elements by visible text */
|
|
24
47
|
findAllByText: (text, options) => queries.findAllByText(getRoot(), text, options),
|
|
48
|
+
/** Find all elements by test ID (widget name) */
|
|
25
49
|
findAllByTestId: (testId, options) => queries.findAllByTestId(getRoot(), testId, options),
|
|
50
|
+
/** Print debug info to console */
|
|
26
51
|
debug: () => {
|
|
27
52
|
console.log("Screen debug - root:", getRoot());
|
|
28
53
|
},
|
package/dist/timing.d.ts
CHANGED
|
@@ -1 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Yields to the event loop, allowing pending GTK events to process.
|
|
3
|
+
*
|
|
4
|
+
* Use this after actions that trigger async widget updates.
|
|
5
|
+
*
|
|
6
|
+
* @returns Promise that resolves on the next event loop tick
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```tsx
|
|
10
|
+
* import { tick } from "@gtkx/testing";
|
|
11
|
+
*
|
|
12
|
+
* widget.setSensitive(false);
|
|
13
|
+
* await tick(); // Wait for GTK to process the change
|
|
14
|
+
* expect(widget.getSensitive()).toBe(false);
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
1
17
|
export declare const tick: () => Promise<void>;
|
package/dist/timing.js
CHANGED
|
@@ -1 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Yields to the event loop, allowing pending GTK events to process.
|
|
3
|
+
*
|
|
4
|
+
* Use this after actions that trigger async widget updates.
|
|
5
|
+
*
|
|
6
|
+
* @returns Promise that resolves on the next event loop tick
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```tsx
|
|
10
|
+
* import { tick } from "@gtkx/testing";
|
|
11
|
+
*
|
|
12
|
+
* widget.setSensitive(false);
|
|
13
|
+
* await tick(); // Wait for GTK to process the change
|
|
14
|
+
* expect(widget.getSensitive()).toBe(false);
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
1
17
|
export const tick = () => new Promise((resolve) => setTimeout(resolve, 0));
|
package/dist/types.d.ts
CHANGED
|
@@ -1,117 +1,124 @@
|
|
|
1
1
|
import type * as Gtk from "@gtkx/ffi/gtk";
|
|
2
2
|
import type { ComponentType, ReactNode } from "react";
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Custom function for matching text content.
|
|
5
|
+
*
|
|
6
|
+
* @param content - The normalized text content to match against
|
|
7
|
+
* @param widget - The widget being tested
|
|
8
|
+
* @returns `true` if the content matches
|
|
6
9
|
*/
|
|
7
10
|
export type TextMatchFunction = (content: string, widget: Gtk.Widget) => boolean;
|
|
8
11
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
12
|
+
* Text matching pattern.
|
|
13
|
+
*
|
|
14
|
+
* Can be a string for exact/substring matching, a RegExp for pattern matching,
|
|
15
|
+
* or a custom function for advanced matching logic.
|
|
11
16
|
*/
|
|
12
17
|
export type TextMatch = string | RegExp | TextMatchFunction;
|
|
13
18
|
/**
|
|
14
|
-
* Options for
|
|
19
|
+
* Options for text normalization before matching.
|
|
15
20
|
*/
|
|
16
21
|
export type NormalizerOptions = {
|
|
17
|
-
/**
|
|
22
|
+
/** Remove leading/trailing whitespace (default: true) */
|
|
18
23
|
trim?: boolean;
|
|
19
|
-
/**
|
|
24
|
+
/** Replace multiple whitespace characters with single space (default: true) */
|
|
20
25
|
collapseWhitespace?: boolean;
|
|
21
26
|
};
|
|
22
27
|
/**
|
|
23
|
-
* Options for text
|
|
28
|
+
* Options for text-based queries.
|
|
24
29
|
*/
|
|
25
30
|
export type TextMatchOptions = {
|
|
26
|
-
/**
|
|
31
|
+
/** Require exact match vs substring match (default: true) */
|
|
27
32
|
exact?: boolean;
|
|
28
|
-
/**
|
|
29
|
-
* Custom function to normalize text before comparison.
|
|
30
|
-
* Cannot be used with trim/collapseWhitespace options.
|
|
31
|
-
*/
|
|
33
|
+
/** Custom text normalizer function */
|
|
32
34
|
normalizer?: (text: string) => string;
|
|
33
|
-
/**
|
|
35
|
+
/** Remove leading/trailing whitespace (default: true) */
|
|
34
36
|
trim?: boolean;
|
|
35
|
-
/**
|
|
37
|
+
/** Replace multiple whitespace with single space (default: true) */
|
|
36
38
|
collapseWhitespace?: boolean;
|
|
37
|
-
/**
|
|
39
|
+
/** Timeout in milliseconds for async queries (default: 1000) */
|
|
38
40
|
timeout?: number;
|
|
39
41
|
};
|
|
40
42
|
/**
|
|
41
|
-
* Options for
|
|
43
|
+
* Options for role-based queries.
|
|
44
|
+
*
|
|
45
|
+
* Extends text matching options with accessible state filters.
|
|
42
46
|
*/
|
|
43
47
|
export type ByRoleOptions = TextMatchOptions & {
|
|
44
|
-
/** Filter by
|
|
48
|
+
/** Filter by accessible name/label */
|
|
45
49
|
name?: TextMatch;
|
|
46
|
-
/** Filter
|
|
50
|
+
/** Filter by checked state (checkboxes, radios, toggles) */
|
|
47
51
|
checked?: boolean;
|
|
48
|
-
/** Filter
|
|
52
|
+
/** Filter by pressed state */
|
|
49
53
|
pressed?: boolean;
|
|
50
|
-
/** Filter
|
|
54
|
+
/** Filter by selected state */
|
|
51
55
|
selected?: boolean;
|
|
52
|
-
/** Filter
|
|
56
|
+
/** Filter by expanded state (expanders) */
|
|
53
57
|
expanded?: boolean;
|
|
54
|
-
/** Filter
|
|
58
|
+
/** Filter by heading level */
|
|
55
59
|
level?: number;
|
|
56
60
|
};
|
|
57
61
|
/**
|
|
58
|
-
* Options for waitFor and
|
|
62
|
+
* Options for {@link waitFor} and {@link waitForElementToBeRemoved}.
|
|
59
63
|
*/
|
|
60
64
|
export type WaitForOptions = {
|
|
61
|
-
/** Maximum time
|
|
65
|
+
/** Maximum time to wait in milliseconds (default: 1000) */
|
|
62
66
|
timeout?: number;
|
|
63
|
-
/**
|
|
67
|
+
/** Polling interval in milliseconds (default: 50) */
|
|
64
68
|
interval?: number;
|
|
65
|
-
/** Custom error handler called
|
|
69
|
+
/** Custom error handler called on timeout */
|
|
66
70
|
onTimeout?: (error: Error) => Error;
|
|
67
71
|
};
|
|
68
72
|
/**
|
|
69
|
-
* Options for
|
|
73
|
+
* Options for {@link render}.
|
|
70
74
|
*/
|
|
71
75
|
export type RenderOptions = {
|
|
72
76
|
/**
|
|
73
|
-
*
|
|
74
|
-
* - `true` (default): Wrap in
|
|
75
|
-
* - `false`: No
|
|
76
|
-
* - Component:
|
|
77
|
+
* Wrapper component or boolean.
|
|
78
|
+
* - `true` (default): Wrap in GtkApplicationWindow
|
|
79
|
+
* - `false`: No wrapper
|
|
80
|
+
* - Component: Custom wrapper component
|
|
77
81
|
*/
|
|
78
82
|
wrapper?: boolean | ComponentType<{
|
|
79
83
|
children: ReactNode;
|
|
80
84
|
}>;
|
|
81
85
|
};
|
|
82
86
|
/**
|
|
83
|
-
* Query methods bound to a
|
|
84
|
-
*
|
|
87
|
+
* Query methods bound to a container.
|
|
88
|
+
*
|
|
89
|
+
* @see {@link screen} for global queries
|
|
90
|
+
* @see {@link within} for scoped queries
|
|
85
91
|
*/
|
|
86
92
|
export type BoundQueries = {
|
|
87
|
-
/** Find
|
|
93
|
+
/** Find single element by accessible role */
|
|
88
94
|
findByRole: (role: Gtk.AccessibleRole, options?: ByRoleOptions) => Promise<Gtk.Widget>;
|
|
89
|
-
/** Find
|
|
95
|
+
/** Find single element by label/text content */
|
|
90
96
|
findByLabelText: (text: TextMatch, options?: TextMatchOptions) => Promise<Gtk.Widget>;
|
|
91
|
-
/** Find
|
|
97
|
+
/** Find single element by visible text */
|
|
92
98
|
findByText: (text: TextMatch, options?: TextMatchOptions) => Promise<Gtk.Widget>;
|
|
93
|
-
/** Find
|
|
99
|
+
/** Find single element by test ID (widget name) */
|
|
94
100
|
findByTestId: (testId: TextMatch, options?: TextMatchOptions) => Promise<Gtk.Widget>;
|
|
95
|
-
/** Find all elements
|
|
101
|
+
/** Find all elements by accessible role */
|
|
96
102
|
findAllByRole: (role: Gtk.AccessibleRole, options?: ByRoleOptions) => Promise<Gtk.Widget[]>;
|
|
97
|
-
/** Find all elements
|
|
103
|
+
/** Find all elements by label/text content */
|
|
98
104
|
findAllByLabelText: (text: TextMatch, options?: TextMatchOptions) => Promise<Gtk.Widget[]>;
|
|
99
|
-
/** Find all elements
|
|
105
|
+
/** Find all elements by visible text */
|
|
100
106
|
findAllByText: (text: TextMatch, options?: TextMatchOptions) => Promise<Gtk.Widget[]>;
|
|
101
|
-
/** Find all elements
|
|
107
|
+
/** Find all elements by test ID (widget name) */
|
|
102
108
|
findAllByTestId: (testId: TextMatch, options?: TextMatchOptions) => Promise<Gtk.Widget[]>;
|
|
103
109
|
};
|
|
104
110
|
/**
|
|
105
|
-
*
|
|
106
|
-
*
|
|
111
|
+
* Result returned by {@link render}.
|
|
112
|
+
*
|
|
113
|
+
* Provides query methods and utilities for testing rendered components.
|
|
107
114
|
*/
|
|
108
115
|
export type RenderResult = BoundQueries & {
|
|
109
|
-
/** The GTK Application
|
|
116
|
+
/** The GTK Application container */
|
|
110
117
|
container: Gtk.Application;
|
|
111
|
-
/** Unmount the rendered component
|
|
118
|
+
/** Unmount the rendered component */
|
|
112
119
|
unmount: () => Promise<void>;
|
|
113
|
-
/** Re-render with a new element
|
|
120
|
+
/** Re-render with a new element */
|
|
114
121
|
rerender: (element: ReactNode) => Promise<void>;
|
|
115
|
-
/** Print the
|
|
122
|
+
/** Print the widget tree to console for debugging */
|
|
116
123
|
debug: () => void;
|
|
117
124
|
};
|
package/dist/user-event.d.ts
CHANGED
|
@@ -1,23 +1,97 @@
|
|
|
1
1
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
2
|
/**
|
|
3
|
-
* Options for
|
|
3
|
+
* Options for tab navigation.
|
|
4
4
|
*/
|
|
5
5
|
export type TabOptions = {
|
|
6
|
-
/**
|
|
6
|
+
/** Navigate backwards (Shift+Tab) instead of forwards */
|
|
7
7
|
shift?: boolean;
|
|
8
8
|
};
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
10
|
+
* User interaction utilities for testing.
|
|
11
|
+
*
|
|
12
|
+
* Simulates user actions like clicking, typing, and selecting.
|
|
13
|
+
* All methods are async and wait for GTK event processing.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```tsx
|
|
17
|
+
* import { render, screen, userEvent } from "@gtkx/testing";
|
|
18
|
+
*
|
|
19
|
+
* test("form submission", async () => {
|
|
20
|
+
* await render(<LoginForm />);
|
|
21
|
+
*
|
|
22
|
+
* const input = await screen.findByRole(Gtk.AccessibleRole.TEXT_BOX);
|
|
23
|
+
* await userEvent.type(input, "username");
|
|
24
|
+
*
|
|
25
|
+
* const button = await screen.findByRole(Gtk.AccessibleRole.BUTTON);
|
|
26
|
+
* await userEvent.click(button);
|
|
27
|
+
* });
|
|
28
|
+
* ```
|
|
12
29
|
*/
|
|
13
30
|
export declare const userEvent: {
|
|
31
|
+
/**
|
|
32
|
+
* Clicks or toggles a widget.
|
|
33
|
+
*
|
|
34
|
+
* For toggleable widgets (checkboxes, switches, toggle buttons),
|
|
35
|
+
* toggles the active state. For buttons, emits clicked signal.
|
|
36
|
+
*/
|
|
14
37
|
click: (element: Gtk.Widget) => Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Double-clicks a widget.
|
|
40
|
+
*
|
|
41
|
+
* Emits two consecutive clicked signals.
|
|
42
|
+
*/
|
|
15
43
|
dblClick: (element: Gtk.Widget) => Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Triple-clicks a widget.
|
|
46
|
+
*
|
|
47
|
+
* Emits three consecutive clicked signals. Useful for text selection.
|
|
48
|
+
*/
|
|
16
49
|
tripleClick: (element: Gtk.Widget) => Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Activates a widget.
|
|
52
|
+
*
|
|
53
|
+
* Calls the widget's activate method.
|
|
54
|
+
*/
|
|
17
55
|
activate: (element: Gtk.Widget) => Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Simulates Tab key navigation.
|
|
58
|
+
*
|
|
59
|
+
* @param element - Starting element
|
|
60
|
+
* @param options - Use `shift: true` for backwards navigation
|
|
61
|
+
*/
|
|
18
62
|
tab: (element: Gtk.Widget, options?: TabOptions) => Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Types text into an editable widget.
|
|
65
|
+
*
|
|
66
|
+
* Appends text to the current content. Works with Entry, SearchEntry,
|
|
67
|
+
* and SpinButton widgets.
|
|
68
|
+
*
|
|
69
|
+
* @param element - The editable widget
|
|
70
|
+
* @param text - Text to type
|
|
71
|
+
*/
|
|
19
72
|
type: (element: Gtk.Widget, text: string) => Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Clears an editable widget's content.
|
|
75
|
+
*
|
|
76
|
+
* Sets the text to empty string.
|
|
77
|
+
*/
|
|
20
78
|
clear: (element: Gtk.Widget) => Promise<void>;
|
|
21
|
-
|
|
79
|
+
/**
|
|
80
|
+
* Selects options in a dropdown or list.
|
|
81
|
+
*
|
|
82
|
+
* Works with DropDown, ComboBox, ListBox, ListView, GridView, and ColumnView.
|
|
83
|
+
*
|
|
84
|
+
* @param element - The selectable widget
|
|
85
|
+
* @param values - Index or array of indices to select
|
|
86
|
+
*/
|
|
87
|
+
selectOptions: (element: Gtk.Widget, values: number | number[]) => Promise<void>;
|
|
88
|
+
/**
|
|
89
|
+
* Deselects options in a list.
|
|
90
|
+
*
|
|
91
|
+
* Works with ListBox and multi-selection list views.
|
|
92
|
+
*
|
|
93
|
+
* @param element - The selectable widget
|
|
94
|
+
* @param values - Index or array of indices to deselect
|
|
95
|
+
*/
|
|
22
96
|
deselectOptions: (element: Gtk.Widget, values: number | number[]) => Promise<void>;
|
|
23
97
|
};
|