@gtkx/testing 0.1.32 → 0.1.34
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 +8 -8
- package/dist/fire-event.js +28 -5
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/queries.d.ts +0 -16
- package/dist/queries.js +24 -102
- package/dist/render.d.ts +3 -3
- package/dist/render.js +15 -49
- package/dist/screen.d.ts +0 -16
- package/dist/screen.js +0 -16
- package/dist/types.d.ts +2 -18
- package/dist/user-event.js +13 -2
- package/dist/widget.d.ts +0 -2
- package/dist/widget.js +0 -3
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -119,10 +119,12 @@ import { AccessibleRole } from "@gtkx/ffi/gtk";
|
|
|
119
119
|
import { App } from "./app.js";
|
|
120
120
|
|
|
121
121
|
// Clean up after each test
|
|
122
|
-
afterEach(() =>
|
|
122
|
+
afterEach(async () => {
|
|
123
|
+
await cleanup();
|
|
124
|
+
});
|
|
123
125
|
|
|
124
126
|
test("increments count when clicking button", async () => {
|
|
125
|
-
render(<App />);
|
|
127
|
+
await render(<App />);
|
|
126
128
|
|
|
127
129
|
const button = await screen.findByRole(AccessibleRole.BUTTON, {
|
|
128
130
|
name: "Increment",
|
|
@@ -132,8 +134,8 @@ test("increments count when clicking button", async () => {
|
|
|
132
134
|
await screen.findByText("Count: 1");
|
|
133
135
|
});
|
|
134
136
|
|
|
135
|
-
test("can also use fireEvent for
|
|
136
|
-
render(<App />);
|
|
137
|
+
test("can also use fireEvent for low-level events", async () => {
|
|
138
|
+
await render(<App />);
|
|
137
139
|
|
|
138
140
|
const button = await screen.findByRole(AccessibleRole.BUTTON, {
|
|
139
141
|
name: "Increment",
|
|
@@ -146,10 +148,8 @@ test("can also use fireEvent for synchronous events", async () => {
|
|
|
146
148
|
|
|
147
149
|
### Available APIs
|
|
148
150
|
|
|
149
|
-
**Queries** - Find elements in the rendered tree:
|
|
150
|
-
- `
|
|
151
|
-
- `queryBy*` / `queryAllBy*` - Returns null/empty array if not found
|
|
152
|
-
- `findBy*` / `findAllBy*` - Async, waits for element
|
|
151
|
+
**Queries** - Find elements in the rendered tree (all async):
|
|
152
|
+
- `findBy*` / `findAllBy*` - Waits for element to appear
|
|
153
153
|
|
|
154
154
|
Query types: `ByRole`, `ByText`, `ByLabelText`, `ByTestId`
|
|
155
155
|
|
package/dist/fire-event.js
CHANGED
|
@@ -1,22 +1,45 @@
|
|
|
1
1
|
import { call } from "@gtkx/native";
|
|
2
|
-
|
|
2
|
+
const hasToggle = (widget) => "getActive" in widget &&
|
|
3
|
+
typeof widget.getActive === "function" &&
|
|
4
|
+
"setActive" in widget &&
|
|
5
|
+
typeof widget.setActive === "function";
|
|
3
6
|
const emitSignal = (widget, signalName) => {
|
|
4
7
|
call("libgobject-2.0.so.0", "g_signal_emit_by_name", [
|
|
5
|
-
{ type: { type: "gobject" }, value:
|
|
8
|
+
{ type: { type: "gobject" }, value: widget.ptr },
|
|
6
9
|
{ type: { type: "string" }, value: signalName },
|
|
7
10
|
], { type: "undefined" });
|
|
8
11
|
};
|
|
9
12
|
export const fireEvent = Object.assign((element, signalName) => {
|
|
10
|
-
|
|
13
|
+
switch (signalName) {
|
|
14
|
+
case "clicked":
|
|
15
|
+
emitSignal(element, "clicked");
|
|
16
|
+
break;
|
|
17
|
+
case "activate":
|
|
18
|
+
element.activate();
|
|
19
|
+
break;
|
|
20
|
+
case "toggled":
|
|
21
|
+
if (hasToggle(element)) {
|
|
22
|
+
element.setActive(!element.getActive());
|
|
23
|
+
}
|
|
24
|
+
break;
|
|
25
|
+
case "changed":
|
|
26
|
+
emitSignal(element, "changed");
|
|
27
|
+
break;
|
|
28
|
+
default:
|
|
29
|
+
throw new Error(`fireEvent: Signal "${signalName}" is not supported. ` +
|
|
30
|
+
`Supported signals: clicked, activate, toggled, changed`);
|
|
31
|
+
}
|
|
11
32
|
}, {
|
|
12
33
|
click: (element) => {
|
|
13
34
|
emitSignal(element, "clicked");
|
|
14
35
|
},
|
|
15
36
|
activate: (element) => {
|
|
16
|
-
|
|
37
|
+
element.activate();
|
|
17
38
|
},
|
|
18
39
|
toggled: (element) => {
|
|
19
|
-
|
|
40
|
+
if (hasToggle(element)) {
|
|
41
|
+
element.setActive(!element.getActive());
|
|
42
|
+
}
|
|
20
43
|
},
|
|
21
44
|
changed: (element) => {
|
|
22
45
|
emitSignal(element, "changed");
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { fireEvent } from "./fire-event.js";
|
|
2
|
-
export { findAllByLabelText, findAllByRole, findAllByTestId, findAllByText, findByLabelText, findByRole, findByTestId, findByText,
|
|
2
|
+
export { findAllByLabelText, findAllByRole, findAllByTestId, findAllByText, findByLabelText, findByRole, findByTestId, findByText, } from "./queries.js";
|
|
3
3
|
export { cleanup, render, teardown } from "./render.js";
|
|
4
4
|
export { screen } from "./screen.js";
|
|
5
5
|
export type { ByRoleOptions, RenderOptions, RenderResult, TextMatchOptions, WaitForOptions, } from "./types.js";
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { fireEvent } from "./fire-event.js";
|
|
2
|
-
export { findAllByLabelText, findAllByRole, findAllByTestId, findAllByText, findByLabelText, findByRole, findByTestId, findByText,
|
|
2
|
+
export { findAllByLabelText, findAllByRole, findAllByTestId, findAllByText, findByLabelText, findByRole, findByTestId, findByText, } from "./queries.js";
|
|
3
3
|
export { cleanup, render, teardown } from "./render.js";
|
|
4
4
|
export { screen } from "./screen.js";
|
|
5
5
|
export { userEvent } from "./user-event.js";
|
package/dist/queries.d.ts
CHANGED
|
@@ -2,22 +2,6 @@ import type * as Gtk from "@gtkx/ffi/gtk";
|
|
|
2
2
|
import { AccessibleRole } from "@gtkx/ffi/gtk";
|
|
3
3
|
import type { ByRoleOptions, TextMatchOptions } from "./types.js";
|
|
4
4
|
type Container = Gtk.Application | Gtk.Widget;
|
|
5
|
-
export declare const getAllByRole: (container: Container, role: AccessibleRole, options?: ByRoleOptions) => Gtk.Widget[];
|
|
6
|
-
export declare const getByRole: (container: Container, role: AccessibleRole, options?: ByRoleOptions) => Gtk.Widget;
|
|
7
|
-
export declare const queryAllByRole: (container: Container, role: AccessibleRole, options?: ByRoleOptions) => Gtk.Widget[];
|
|
8
|
-
export declare const queryByRole: (container: Container, role: AccessibleRole, options?: ByRoleOptions) => Gtk.Widget | null;
|
|
9
|
-
export declare const getAllByLabelText: (container: Container, text: string | RegExp, options?: TextMatchOptions) => Gtk.Widget[];
|
|
10
|
-
export declare const getByLabelText: (container: Container, text: string | RegExp, options?: TextMatchOptions) => Gtk.Widget;
|
|
11
|
-
export declare const queryAllByLabelText: (container: Container, text: string | RegExp, options?: TextMatchOptions) => Gtk.Widget[];
|
|
12
|
-
export declare const queryByLabelText: (container: Container, text: string | RegExp, options?: TextMatchOptions) => Gtk.Widget | null;
|
|
13
|
-
export declare const getAllByText: (container: Container, text: string | RegExp, options?: TextMatchOptions) => Gtk.Widget[];
|
|
14
|
-
export declare const getByText: (container: Container, text: string | RegExp, options?: TextMatchOptions) => Gtk.Widget;
|
|
15
|
-
export declare const queryAllByText: (container: Container, text: string | RegExp, options?: TextMatchOptions) => Gtk.Widget[];
|
|
16
|
-
export declare const queryByText: (container: Container, text: string | RegExp, options?: TextMatchOptions) => Gtk.Widget | null;
|
|
17
|
-
export declare const getAllByTestId: (container: Container, testId: string | RegExp, options?: TextMatchOptions) => Gtk.Widget[];
|
|
18
|
-
export declare const getByTestId: (container: Container, testId: string | RegExp, options?: TextMatchOptions) => Gtk.Widget;
|
|
19
|
-
export declare const queryAllByTestId: (container: Container, testId: string | RegExp, options?: TextMatchOptions) => Gtk.Widget[];
|
|
20
|
-
export declare const queryByTestId: (container: Container, testId: string | RegExp, options?: TextMatchOptions) => Gtk.Widget | null;
|
|
21
5
|
export declare const findByRole: (container: Container, role: AccessibleRole, options?: ByRoleOptions) => Promise<Gtk.Widget>;
|
|
22
6
|
export declare const findAllByRole: (container: Container, role: AccessibleRole, options?: ByRoleOptions) => Promise<Gtk.Widget[]>;
|
|
23
7
|
export declare const findByLabelText: (container: Container, text: string | RegExp, options?: TextMatchOptions) => Promise<Gtk.Widget>;
|
package/dist/queries.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { wrapPtr } from "@gtkx/ffi";
|
|
2
|
+
import { AccessibleRole, Button, CheckButton, Expander, Label, ToggleButton } from "@gtkx/ffi/gtk";
|
|
3
3
|
import { findAll } from "./traversal.js";
|
|
4
4
|
import { waitFor } from "./wait-for.js";
|
|
5
|
-
import { getWidgetPtr } from "./widget.js";
|
|
6
5
|
const DEFAULT_NORMALIZER = (text) => text.trim().replace(/\s+/g, " ");
|
|
7
6
|
const normalizeText = (text, options) => {
|
|
8
7
|
const normalizer = options?.normalizer ?? DEFAULT_NORMALIZER;
|
|
@@ -19,13 +18,11 @@ const matchText = (actual, expected, options) => {
|
|
|
19
18
|
}
|
|
20
19
|
return expected.test(normalizedActual);
|
|
21
20
|
};
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return result;
|
|
28
|
-
};
|
|
21
|
+
const asButton = (widget) => wrapPtr(widget.ptr, Button);
|
|
22
|
+
const asLabel = (widget) => wrapPtr(widget.ptr, Label);
|
|
23
|
+
const asCheckButton = (widget) => wrapPtr(widget.ptr, CheckButton);
|
|
24
|
+
const asToggleButton = (widget) => wrapPtr(widget.ptr, ToggleButton);
|
|
25
|
+
const asExpander = (widget) => wrapPtr(widget.ptr, Expander);
|
|
29
26
|
const isInternalLabel = (widget) => {
|
|
30
27
|
const accessible = widget;
|
|
31
28
|
if (accessible.getAccessibleRole() !== AccessibleRole.LABEL)
|
|
@@ -44,9 +41,6 @@ const isInternalLabel = (widget) => {
|
|
|
44
41
|
parentRole === AccessibleRole.MENU_ITEM_RADIO);
|
|
45
42
|
};
|
|
46
43
|
const getWidgetText = (widget) => {
|
|
47
|
-
const ptr = getWidgetPtr(widget);
|
|
48
|
-
if (!ptr)
|
|
49
|
-
return null;
|
|
50
44
|
if (isInternalLabel(widget))
|
|
51
45
|
return null;
|
|
52
46
|
const accessible = widget;
|
|
@@ -59,57 +53,39 @@ const getWidgetText = (widget) => {
|
|
|
59
53
|
case AccessibleRole.MENU_ITEM:
|
|
60
54
|
case AccessibleRole.MENU_ITEM_CHECKBOX:
|
|
61
55
|
case AccessibleRole.MENU_ITEM_RADIO:
|
|
62
|
-
return
|
|
56
|
+
return asButton(widget).getLabel();
|
|
63
57
|
case AccessibleRole.LABEL:
|
|
64
|
-
return
|
|
58
|
+
return asLabel(widget).getLabel();
|
|
65
59
|
case AccessibleRole.TEXT_BOX:
|
|
66
60
|
case AccessibleRole.SEARCH_BOX:
|
|
67
61
|
case AccessibleRole.SPIN_BUTTON:
|
|
68
|
-
return
|
|
62
|
+
return widget.getText();
|
|
69
63
|
default:
|
|
70
64
|
return null;
|
|
71
65
|
}
|
|
72
66
|
};
|
|
73
67
|
const getWidgetTestId = (widget) => {
|
|
74
|
-
|
|
75
|
-
if (!ptr)
|
|
76
|
-
return null;
|
|
77
|
-
const result = call("libgtk-4.so.1", "gtk_widget_get_name", [{ type: { type: "gobject" }, value: ptr }], {
|
|
78
|
-
type: "string",
|
|
79
|
-
borrowed: true,
|
|
80
|
-
});
|
|
81
|
-
return result;
|
|
68
|
+
return widget.getName();
|
|
82
69
|
};
|
|
83
70
|
const getWidgetCheckedState = (widget) => {
|
|
84
|
-
const ptr = getWidgetPtr(widget);
|
|
85
|
-
if (!ptr)
|
|
86
|
-
return undefined;
|
|
87
71
|
const accessible = widget;
|
|
88
72
|
const role = accessible.getAccessibleRole();
|
|
89
73
|
if (role === AccessibleRole.CHECKBOX || role === AccessibleRole.RADIO) {
|
|
90
|
-
|
|
91
|
-
type: "boolean",
|
|
92
|
-
});
|
|
93
|
-
return result === true;
|
|
74
|
+
return asCheckButton(widget).getActive();
|
|
94
75
|
}
|
|
95
76
|
if (role === AccessibleRole.TOGGLE_BUTTON) {
|
|
96
|
-
|
|
97
|
-
return result === true;
|
|
77
|
+
return asToggleButton(widget).getActive();
|
|
98
78
|
}
|
|
99
79
|
return undefined;
|
|
100
80
|
};
|
|
101
81
|
const getWidgetExpandedState = (widget) => {
|
|
102
|
-
const ptr = getWidgetPtr(widget);
|
|
103
|
-
if (!ptr)
|
|
104
|
-
return undefined;
|
|
105
82
|
const accessible = widget;
|
|
106
83
|
const role = accessible.getAccessibleRole();
|
|
107
84
|
if (role === AccessibleRole.BUTTON) {
|
|
108
|
-
const
|
|
109
|
-
if (!
|
|
85
|
+
const parent = widget.getParent();
|
|
86
|
+
if (!parent)
|
|
110
87
|
return undefined;
|
|
111
|
-
|
|
112
|
-
return result === true;
|
|
88
|
+
return asExpander(parent).getExpanded();
|
|
113
89
|
}
|
|
114
90
|
return undefined;
|
|
115
91
|
};
|
|
@@ -150,7 +126,7 @@ const formatByRoleError = (role, options) => {
|
|
|
150
126
|
parts.push(`level=${options.level}`);
|
|
151
127
|
return parts.join(" and ");
|
|
152
128
|
};
|
|
153
|
-
|
|
129
|
+
const getAllByRole = (container, role, options) => {
|
|
154
130
|
const matches = findAll(container, (node) => {
|
|
155
131
|
const accessible = node;
|
|
156
132
|
if (accessible.getAccessibleRole() !== role)
|
|
@@ -162,29 +138,14 @@ export const getAllByRole = (container, role, options) => {
|
|
|
162
138
|
}
|
|
163
139
|
return matches;
|
|
164
140
|
};
|
|
165
|
-
|
|
141
|
+
const getByRole = (container, role, options) => {
|
|
166
142
|
const matches = getAllByRole(container, role, options);
|
|
167
143
|
if (matches.length > 1) {
|
|
168
144
|
throw new Error(`Found ${matches.length} elements with ${formatByRoleError(role, options)}`);
|
|
169
145
|
}
|
|
170
146
|
return matches[0];
|
|
171
147
|
};
|
|
172
|
-
|
|
173
|
-
return findAll(container, (node) => {
|
|
174
|
-
const accessible = node;
|
|
175
|
-
if (accessible.getAccessibleRole() !== role)
|
|
176
|
-
return false;
|
|
177
|
-
return matchByRoleOptions(node, options);
|
|
178
|
-
});
|
|
179
|
-
};
|
|
180
|
-
export const queryByRole = (container, role, options) => {
|
|
181
|
-
const matches = queryAllByRole(container, role, options);
|
|
182
|
-
if (matches.length > 1) {
|
|
183
|
-
throw new Error(`Found ${matches.length} elements with ${formatByRoleError(role, options)}`);
|
|
184
|
-
}
|
|
185
|
-
return matches[0] ?? null;
|
|
186
|
-
};
|
|
187
|
-
export const getAllByLabelText = (container, text, options) => {
|
|
148
|
+
const getAllByLabelText = (container, text, options) => {
|
|
188
149
|
const matches = findAll(container, (node) => {
|
|
189
150
|
const widgetText = getWidgetText(node);
|
|
190
151
|
return matchText(widgetText, text, options);
|
|
@@ -194,27 +155,14 @@ export const getAllByLabelText = (container, text, options) => {
|
|
|
194
155
|
}
|
|
195
156
|
return matches;
|
|
196
157
|
};
|
|
197
|
-
|
|
158
|
+
const getByLabelText = (container, text, options) => {
|
|
198
159
|
const matches = getAllByLabelText(container, text, options);
|
|
199
160
|
if (matches.length > 1) {
|
|
200
161
|
throw new Error(`Found ${matches.length} elements with label text "${text}"`);
|
|
201
162
|
}
|
|
202
163
|
return matches[0];
|
|
203
164
|
};
|
|
204
|
-
|
|
205
|
-
return findAll(container, (node) => {
|
|
206
|
-
const widgetText = getWidgetText(node);
|
|
207
|
-
return matchText(widgetText, text, options);
|
|
208
|
-
});
|
|
209
|
-
};
|
|
210
|
-
export const queryByLabelText = (container, text, options) => {
|
|
211
|
-
const matches = queryAllByLabelText(container, text, options);
|
|
212
|
-
if (matches.length > 1) {
|
|
213
|
-
throw new Error(`Found ${matches.length} elements with label text "${text}"`);
|
|
214
|
-
}
|
|
215
|
-
return matches[0] ?? null;
|
|
216
|
-
};
|
|
217
|
-
export const getAllByText = (container, text, options) => {
|
|
165
|
+
const getAllByText = (container, text, options) => {
|
|
218
166
|
const matches = findAll(container, (node) => {
|
|
219
167
|
const widgetText = getWidgetText(node);
|
|
220
168
|
return matchText(widgetText, text, options);
|
|
@@ -224,27 +172,14 @@ export const getAllByText = (container, text, options) => {
|
|
|
224
172
|
}
|
|
225
173
|
return matches;
|
|
226
174
|
};
|
|
227
|
-
|
|
175
|
+
const getByText = (container, text, options) => {
|
|
228
176
|
const matches = getAllByText(container, text, options);
|
|
229
177
|
if (matches.length > 1) {
|
|
230
178
|
throw new Error(`Found ${matches.length} elements with text "${text}"`);
|
|
231
179
|
}
|
|
232
180
|
return matches[0];
|
|
233
181
|
};
|
|
234
|
-
|
|
235
|
-
return findAll(container, (node) => {
|
|
236
|
-
const widgetText = getWidgetText(node);
|
|
237
|
-
return matchText(widgetText, text, options);
|
|
238
|
-
});
|
|
239
|
-
};
|
|
240
|
-
export const queryByText = (container, text, options) => {
|
|
241
|
-
const matches = queryAllByText(container, text, options);
|
|
242
|
-
if (matches.length > 1) {
|
|
243
|
-
throw new Error(`Found ${matches.length} elements with text "${text}"`);
|
|
244
|
-
}
|
|
245
|
-
return matches[0] ?? null;
|
|
246
|
-
};
|
|
247
|
-
export const getAllByTestId = (container, testId, options) => {
|
|
182
|
+
const getAllByTestId = (container, testId, options) => {
|
|
248
183
|
const matches = findAll(container, (node) => {
|
|
249
184
|
const widgetTestId = getWidgetTestId(node);
|
|
250
185
|
return matchText(widgetTestId, testId, options);
|
|
@@ -254,26 +189,13 @@ export const getAllByTestId = (container, testId, options) => {
|
|
|
254
189
|
}
|
|
255
190
|
return matches;
|
|
256
191
|
};
|
|
257
|
-
|
|
192
|
+
const getByTestId = (container, testId, options) => {
|
|
258
193
|
const matches = getAllByTestId(container, testId, options);
|
|
259
194
|
if (matches.length > 1) {
|
|
260
195
|
throw new Error(`Found ${matches.length} elements with test id "${testId}"`);
|
|
261
196
|
}
|
|
262
197
|
return matches[0];
|
|
263
198
|
};
|
|
264
|
-
export const queryAllByTestId = (container, testId, options) => {
|
|
265
|
-
return findAll(container, (node) => {
|
|
266
|
-
const widgetTestId = getWidgetTestId(node);
|
|
267
|
-
return matchText(widgetTestId, testId, options);
|
|
268
|
-
});
|
|
269
|
-
};
|
|
270
|
-
export const queryByTestId = (container, testId, options) => {
|
|
271
|
-
const matches = queryAllByTestId(container, testId, options);
|
|
272
|
-
if (matches.length > 1) {
|
|
273
|
-
throw new Error(`Found ${matches.length} elements with test id "${testId}"`);
|
|
274
|
-
}
|
|
275
|
-
return matches[0] ?? null;
|
|
276
|
-
};
|
|
277
199
|
export const findByRole = async (container, role, options) => waitFor(() => getByRole(container, role, options));
|
|
278
200
|
export const findAllByRole = async (container, role, options) => waitFor(() => getAllByRole(container, role, options));
|
|
279
201
|
export const findByLabelText = async (container, text, options) => waitFor(() => getByLabelText(container, text, options));
|
package/dist/render.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
2
|
import type { RenderOptions, RenderResult } from "./types.js";
|
|
3
|
-
export declare const render: (element: ReactNode, options?: RenderOptions) => RenderResult
|
|
4
|
-
export declare const cleanup: () => void
|
|
5
|
-
export declare const teardown: () => void
|
|
3
|
+
export declare const render: (element: ReactNode, options?: RenderOptions) => Promise<RenderResult>;
|
|
4
|
+
export declare const cleanup: () => Promise<void>;
|
|
5
|
+
export declare const teardown: () => Promise<void>;
|
package/dist/render.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { start, stop } from "@gtkx/ffi";
|
|
3
3
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
4
|
-
import { reconciler } from "@gtkx/react";
|
|
4
|
+
import { ApplicationWindow, reconciler } from "@gtkx/react";
|
|
5
5
|
import * as queries from "./queries.js";
|
|
6
6
|
import { setScreenRoot } from "./screen.js";
|
|
7
7
|
const APP_ID = "com.gtkx.testing";
|
|
@@ -21,25 +21,10 @@ const printWidgetTree = (root, indent = 0) => {
|
|
|
21
21
|
}
|
|
22
22
|
return result;
|
|
23
23
|
};
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
instance.updateContainer(element, fiberRoot, null, () => { });
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
if (typeof instanceAny.updateContainerSync === "function") {
|
|
33
|
-
instanceAny.updateContainerSync(element, fiberRoot, null, () => { });
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
instance.updateContainer(element, fiberRoot, null, () => { });
|
|
37
|
-
}
|
|
38
|
-
if (typeof instanceAny.flushSyncWork === "function") {
|
|
39
|
-
instanceAny.flushSyncWork();
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
instance.flushPassiveEffects();
|
|
24
|
+
const tick = () => new Promise((resolve) => setTimeout(resolve, 0));
|
|
25
|
+
const update = async (instance, element, fiberRoot) => {
|
|
26
|
+
instance.updateContainer(element, fiberRoot, null, () => { });
|
|
27
|
+
await tick();
|
|
43
28
|
};
|
|
44
29
|
const ensureInitialized = () => {
|
|
45
30
|
if (!app) {
|
|
@@ -57,35 +42,16 @@ const ensureInitialized = () => {
|
|
|
57
42
|
}
|
|
58
43
|
return { app, container };
|
|
59
44
|
};
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
return _jsx(Wrapper, { children: element });
|
|
64
|
-
};
|
|
65
|
-
export const render = (element, options) => {
|
|
45
|
+
const DefaultWrapper = ({ children }) => (_jsx(ApplicationWindow, { children: children }));
|
|
46
|
+
const wrapElement = (element, Wrapper = DefaultWrapper) => (_jsx(Wrapper, { children: element }));
|
|
47
|
+
export const render = async (element, options) => {
|
|
66
48
|
const { app: application, container: fiberRoot } = ensureInitialized();
|
|
67
49
|
const instance = reconciler.getInstance();
|
|
68
50
|
const wrappedElement = wrapElement(element, options?.wrapper);
|
|
69
|
-
|
|
51
|
+
await update(instance, wrappedElement, fiberRoot);
|
|
70
52
|
setScreenRoot(application);
|
|
71
53
|
return {
|
|
72
54
|
container: application,
|
|
73
|
-
getByRole: (role, opts) => queries.getByRole(application, role, opts),
|
|
74
|
-
getByLabelText: (text, opts) => queries.getByLabelText(application, text, opts),
|
|
75
|
-
getByText: (text, opts) => queries.getByText(application, text, opts),
|
|
76
|
-
getByTestId: (testId, opts) => queries.getByTestId(application, testId, opts),
|
|
77
|
-
queryByRole: (role, opts) => queries.queryByRole(application, role, opts),
|
|
78
|
-
queryByLabelText: (text, opts) => queries.queryByLabelText(application, text, opts),
|
|
79
|
-
queryByText: (text, opts) => queries.queryByText(application, text, opts),
|
|
80
|
-
queryByTestId: (testId, opts) => queries.queryByTestId(application, testId, opts),
|
|
81
|
-
getAllByRole: (role, opts) => queries.getAllByRole(application, role, opts),
|
|
82
|
-
getAllByLabelText: (text, opts) => queries.getAllByLabelText(application, text, opts),
|
|
83
|
-
getAllByText: (text, opts) => queries.getAllByText(application, text, opts),
|
|
84
|
-
getAllByTestId: (testId, opts) => queries.getAllByTestId(application, testId, opts),
|
|
85
|
-
queryAllByRole: (role, opts) => queries.queryAllByRole(application, role, opts),
|
|
86
|
-
queryAllByLabelText: (text, opts) => queries.queryAllByLabelText(application, text, opts),
|
|
87
|
-
queryAllByText: (text, opts) => queries.queryAllByText(application, text, opts),
|
|
88
|
-
queryAllByTestId: (testId, opts) => queries.queryAllByTestId(application, testId, opts),
|
|
89
55
|
findByRole: (role, opts) => queries.findByRole(application, role, opts),
|
|
90
56
|
findByLabelText: (text, opts) => queries.findByLabelText(application, text, opts),
|
|
91
57
|
findByText: (text, opts) => queries.findByText(application, text, opts),
|
|
@@ -94,10 +60,10 @@ export const render = (element, options) => {
|
|
|
94
60
|
findAllByLabelText: (text, opts) => queries.findAllByLabelText(application, text, opts),
|
|
95
61
|
findAllByText: (text, opts) => queries.findAllByText(application, text, opts),
|
|
96
62
|
findAllByTestId: (testId, opts) => queries.findAllByTestId(application, testId, opts),
|
|
97
|
-
unmount: () =>
|
|
63
|
+
unmount: () => update(instance, null, fiberRoot),
|
|
98
64
|
rerender: (newElement) => {
|
|
99
65
|
const wrapped = wrapElement(newElement, options?.wrapper);
|
|
100
|
-
|
|
66
|
+
return update(instance, wrapped, fiberRoot);
|
|
101
67
|
},
|
|
102
68
|
debug: () => {
|
|
103
69
|
const activeWindow = application.getActiveWindow();
|
|
@@ -107,10 +73,10 @@ export const render = (element, options) => {
|
|
|
107
73
|
},
|
|
108
74
|
};
|
|
109
75
|
};
|
|
110
|
-
export const cleanup = () => {
|
|
76
|
+
export const cleanup = async () => {
|
|
111
77
|
if (container && app) {
|
|
112
78
|
const instance = reconciler.getInstance();
|
|
113
|
-
|
|
79
|
+
await update(instance, null, container);
|
|
114
80
|
for (const window of app.getWindows()) {
|
|
115
81
|
window.destroy();
|
|
116
82
|
}
|
|
@@ -118,9 +84,9 @@ export const cleanup = () => {
|
|
|
118
84
|
container = null;
|
|
119
85
|
setScreenRoot(null);
|
|
120
86
|
};
|
|
121
|
-
export const teardown = () => {
|
|
87
|
+
export const teardown = async () => {
|
|
122
88
|
if (app) {
|
|
123
|
-
cleanup();
|
|
89
|
+
await cleanup();
|
|
124
90
|
stop();
|
|
125
91
|
app = null;
|
|
126
92
|
container = null;
|
package/dist/screen.d.ts
CHANGED
|
@@ -3,22 +3,6 @@ import type { AccessibleRole } from "@gtkx/ffi/gtk";
|
|
|
3
3
|
import type { ByRoleOptions, TextMatchOptions } from "./types.js";
|
|
4
4
|
export declare const setScreenRoot: (root: Gtk.Application | null) => void;
|
|
5
5
|
export declare const screen: {
|
|
6
|
-
getByRole: (role: AccessibleRole, options?: ByRoleOptions) => Gtk.Widget;
|
|
7
|
-
getByLabelText: (text: string | RegExp, options?: TextMatchOptions) => Gtk.Widget;
|
|
8
|
-
getByText: (text: string | RegExp, options?: TextMatchOptions) => Gtk.Widget;
|
|
9
|
-
getByTestId: (testId: string | RegExp, options?: TextMatchOptions) => Gtk.Widget;
|
|
10
|
-
queryByRole: (role: AccessibleRole, options?: ByRoleOptions) => Gtk.Widget | null;
|
|
11
|
-
queryByLabelText: (text: string | RegExp, options?: TextMatchOptions) => Gtk.Widget | null;
|
|
12
|
-
queryByText: (text: string | RegExp, options?: TextMatchOptions) => Gtk.Widget | null;
|
|
13
|
-
queryByTestId: (testId: string | RegExp, options?: TextMatchOptions) => Gtk.Widget | null;
|
|
14
|
-
getAllByRole: (role: AccessibleRole, options?: ByRoleOptions) => Gtk.Widget[];
|
|
15
|
-
getAllByLabelText: (text: string | RegExp, options?: TextMatchOptions) => Gtk.Widget[];
|
|
16
|
-
getAllByText: (text: string | RegExp, options?: TextMatchOptions) => Gtk.Widget[];
|
|
17
|
-
getAllByTestId: (testId: string | RegExp, options?: TextMatchOptions) => Gtk.Widget[];
|
|
18
|
-
queryAllByRole: (role: AccessibleRole, options?: ByRoleOptions) => Gtk.Widget[];
|
|
19
|
-
queryAllByLabelText: (text: string | RegExp, options?: TextMatchOptions) => Gtk.Widget[];
|
|
20
|
-
queryAllByText: (text: string | RegExp, options?: TextMatchOptions) => Gtk.Widget[];
|
|
21
|
-
queryAllByTestId: (testId: string | RegExp, options?: TextMatchOptions) => Gtk.Widget[];
|
|
22
6
|
findByRole: (role: AccessibleRole, options?: ByRoleOptions) => Promise<Gtk.Widget>;
|
|
23
7
|
findByLabelText: (text: string | RegExp, options?: TextMatchOptions) => Promise<Gtk.Widget>;
|
|
24
8
|
findByText: (text: string | RegExp, options?: TextMatchOptions) => Promise<Gtk.Widget>;
|
package/dist/screen.js
CHANGED
|
@@ -10,22 +10,6 @@ const getRoot = () => {
|
|
|
10
10
|
return currentRoot;
|
|
11
11
|
};
|
|
12
12
|
export const screen = {
|
|
13
|
-
getByRole: (role, options) => queries.getByRole(getRoot(), role, options),
|
|
14
|
-
getByLabelText: (text, options) => queries.getByLabelText(getRoot(), text, options),
|
|
15
|
-
getByText: (text, options) => queries.getByText(getRoot(), text, options),
|
|
16
|
-
getByTestId: (testId, options) => queries.getByTestId(getRoot(), testId, options),
|
|
17
|
-
queryByRole: (role, options) => queries.queryByRole(getRoot(), role, options),
|
|
18
|
-
queryByLabelText: (text, options) => queries.queryByLabelText(getRoot(), text, options),
|
|
19
|
-
queryByText: (text, options) => queries.queryByText(getRoot(), text, options),
|
|
20
|
-
queryByTestId: (testId, options) => queries.queryByTestId(getRoot(), testId, options),
|
|
21
|
-
getAllByRole: (role, options) => queries.getAllByRole(getRoot(), role, options),
|
|
22
|
-
getAllByLabelText: (text, options) => queries.getAllByLabelText(getRoot(), text, options),
|
|
23
|
-
getAllByText: (text, options) => queries.getAllByText(getRoot(), text, options),
|
|
24
|
-
getAllByTestId: (testId, options) => queries.getAllByTestId(getRoot(), testId, options),
|
|
25
|
-
queryAllByRole: (role, options) => queries.queryAllByRole(getRoot(), role, options),
|
|
26
|
-
queryAllByLabelText: (text, options) => queries.queryAllByLabelText(getRoot(), text, options),
|
|
27
|
-
queryAllByText: (text, options) => queries.queryAllByText(getRoot(), text, options),
|
|
28
|
-
queryAllByTestId: (testId, options) => queries.queryAllByTestId(getRoot(), testId, options),
|
|
29
13
|
findByRole: (role, options) => queries.findByRole(getRoot(), role, options),
|
|
30
14
|
findByLabelText: (text, options) => queries.findByLabelText(getRoot(), text, options),
|
|
31
15
|
findByText: (text, options) => queries.findByText(getRoot(), text, options),
|
package/dist/types.d.ts
CHANGED
|
@@ -25,22 +25,6 @@ export interface RenderOptions {
|
|
|
25
25
|
}
|
|
26
26
|
export interface RenderResult {
|
|
27
27
|
container: Gtk.Application;
|
|
28
|
-
getByRole: (role: AccessibleRole, options?: ByRoleOptions) => Gtk.Widget;
|
|
29
|
-
getByLabelText: (text: string | RegExp, options?: TextMatchOptions) => Gtk.Widget;
|
|
30
|
-
getByText: (text: string | RegExp, options?: TextMatchOptions) => Gtk.Widget;
|
|
31
|
-
getByTestId: (testId: string | RegExp, options?: TextMatchOptions) => Gtk.Widget;
|
|
32
|
-
queryByRole: (role: AccessibleRole, options?: ByRoleOptions) => Gtk.Widget | null;
|
|
33
|
-
queryByLabelText: (text: string | RegExp, options?: TextMatchOptions) => Gtk.Widget | null;
|
|
34
|
-
queryByText: (text: string | RegExp, options?: TextMatchOptions) => Gtk.Widget | null;
|
|
35
|
-
queryByTestId: (testId: string | RegExp, options?: TextMatchOptions) => Gtk.Widget | null;
|
|
36
|
-
getAllByRole: (role: AccessibleRole, options?: ByRoleOptions) => Gtk.Widget[];
|
|
37
|
-
getAllByLabelText: (text: string | RegExp, options?: TextMatchOptions) => Gtk.Widget[];
|
|
38
|
-
getAllByText: (text: string | RegExp, options?: TextMatchOptions) => Gtk.Widget[];
|
|
39
|
-
getAllByTestId: (testId: string | RegExp, options?: TextMatchOptions) => Gtk.Widget[];
|
|
40
|
-
queryAllByRole: (role: AccessibleRole, options?: ByRoleOptions) => Gtk.Widget[];
|
|
41
|
-
queryAllByLabelText: (text: string | RegExp, options?: TextMatchOptions) => Gtk.Widget[];
|
|
42
|
-
queryAllByText: (text: string | RegExp, options?: TextMatchOptions) => Gtk.Widget[];
|
|
43
|
-
queryAllByTestId: (testId: string | RegExp, options?: TextMatchOptions) => Gtk.Widget[];
|
|
44
28
|
findByRole: (role: AccessibleRole, options?: ByRoleOptions) => Promise<Gtk.Widget>;
|
|
45
29
|
findByLabelText: (text: string | RegExp, options?: TextMatchOptions) => Promise<Gtk.Widget>;
|
|
46
30
|
findByText: (text: string | RegExp, options?: TextMatchOptions) => Promise<Gtk.Widget>;
|
|
@@ -49,7 +33,7 @@ export interface RenderResult {
|
|
|
49
33
|
findAllByLabelText: (text: string | RegExp, options?: TextMatchOptions) => Promise<Gtk.Widget[]>;
|
|
50
34
|
findAllByText: (text: string | RegExp, options?: TextMatchOptions) => Promise<Gtk.Widget[]>;
|
|
51
35
|
findAllByTestId: (testId: string | RegExp, options?: TextMatchOptions) => Promise<Gtk.Widget[]>;
|
|
52
|
-
unmount: () => void
|
|
53
|
-
rerender: (element: ReactNode) => void
|
|
36
|
+
unmount: () => Promise<void>;
|
|
37
|
+
rerender: (element: ReactNode) => Promise<void>;
|
|
54
38
|
debug: () => void;
|
|
55
39
|
}
|
package/dist/user-event.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { call } from "@gtkx/native";
|
|
2
|
-
import {
|
|
2
|
+
import { hasGetText, hasSetText } from "./widget.js";
|
|
3
|
+
const tick = () => new Promise((resolve) => setTimeout(resolve, 0));
|
|
3
4
|
const emitSignal = (widget, signalName) => {
|
|
4
5
|
call("libgobject-2.0.so.0", "g_signal_emit_by_name", [
|
|
5
|
-
{ type: { type: "gobject" }, value:
|
|
6
|
+
{ type: { type: "gobject" }, value: widget.ptr },
|
|
6
7
|
{ type: { type: "string" }, value: signalName },
|
|
7
8
|
], { type: "undefined" });
|
|
8
9
|
};
|
|
@@ -10,10 +11,13 @@ const createUserEventInstance = (_options) => {
|
|
|
10
11
|
return {
|
|
11
12
|
click: async (element) => {
|
|
12
13
|
emitSignal(element, "clicked");
|
|
14
|
+
await tick();
|
|
13
15
|
},
|
|
14
16
|
dblClick: async (element) => {
|
|
15
17
|
emitSignal(element, "clicked");
|
|
18
|
+
await tick();
|
|
16
19
|
emitSignal(element, "clicked");
|
|
20
|
+
await tick();
|
|
17
21
|
},
|
|
18
22
|
type: async (element, text) => {
|
|
19
23
|
if (!hasSetText(element)) {
|
|
@@ -21,12 +25,14 @@ const createUserEventInstance = (_options) => {
|
|
|
21
25
|
}
|
|
22
26
|
const currentText = hasGetText(element) ? element.getText() : "";
|
|
23
27
|
element.setText(currentText + text);
|
|
28
|
+
await tick();
|
|
24
29
|
},
|
|
25
30
|
clear: async (element) => {
|
|
26
31
|
if (!hasSetText(element)) {
|
|
27
32
|
throw new Error("Cannot clear element: no setText method available");
|
|
28
33
|
}
|
|
29
34
|
element.setText("");
|
|
35
|
+
await tick();
|
|
30
36
|
},
|
|
31
37
|
};
|
|
32
38
|
};
|
|
@@ -34,10 +40,13 @@ export const userEvent = {
|
|
|
34
40
|
setup: (options) => createUserEventInstance(options),
|
|
35
41
|
click: async (element) => {
|
|
36
42
|
emitSignal(element, "clicked");
|
|
43
|
+
await tick();
|
|
37
44
|
},
|
|
38
45
|
dblClick: async (element) => {
|
|
39
46
|
emitSignal(element, "clicked");
|
|
47
|
+
await tick();
|
|
40
48
|
emitSignal(element, "clicked");
|
|
49
|
+
await tick();
|
|
41
50
|
},
|
|
42
51
|
type: async (element, text) => {
|
|
43
52
|
if (!hasSetText(element)) {
|
|
@@ -45,11 +54,13 @@ export const userEvent = {
|
|
|
45
54
|
}
|
|
46
55
|
const currentText = hasGetText(element) ? element.getText() : "";
|
|
47
56
|
element.setText(currentText + text);
|
|
57
|
+
await tick();
|
|
48
58
|
},
|
|
49
59
|
clear: async (element) => {
|
|
50
60
|
if (!hasSetText(element)) {
|
|
51
61
|
throw new Error("Cannot clear element: no setText method available");
|
|
52
62
|
}
|
|
53
63
|
element.setText("");
|
|
64
|
+
await tick();
|
|
54
65
|
},
|
|
55
66
|
};
|
package/dist/widget.d.ts
CHANGED
package/dist/widget.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gtkx/testing",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.34",
|
|
4
4
|
"description": "Testing utilities for GTKX applications",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"gtk",
|
|
@@ -32,9 +32,9 @@
|
|
|
32
32
|
"dist"
|
|
33
33
|
],
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@gtkx/ffi": "0.1.
|
|
36
|
-
"@gtkx/
|
|
37
|
-
"@gtkx/
|
|
35
|
+
"@gtkx/ffi": "0.1.34",
|
|
36
|
+
"@gtkx/react": "0.1.34",
|
|
37
|
+
"@gtkx/native": "0.1.34"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
40
|
"build": "tsc -b && cp ../../README.md .",
|