@gtkx/testing 1.0.0-rc.4 → 1.1.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 +5 -5
- package/dist/accessible-native.d.ts +16 -0
- package/dist/accessible-native.d.ts.map +1 -0
- package/dist/accessible-native.js +206 -0
- package/dist/accessible-native.js.map +1 -0
- package/dist/act.d.ts +1 -3
- package/dist/act.d.ts.map +1 -1
- package/dist/act.js +1 -1
- package/dist/act.js.map +1 -1
- package/dist/build-queries.d.ts +27 -10
- package/dist/build-queries.d.ts.map +1 -1
- package/dist/build-queries.js +22 -24
- package/dist/build-queries.js.map +1 -1
- package/dist/cleanup-registry.d.ts +1 -1
- package/dist/cleanup-registry.d.ts.map +1 -1
- package/dist/cleanup-registry.js.map +1 -1
- package/dist/config.d.ts +8 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/errors.d.ts +10 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +10 -1
- package/dist/errors.js.map +1 -1
- package/dist/fire-event.d.ts +35 -6
- package/dist/fire-event.d.ts.map +1 -1
- package/dist/fire-event.js +23 -7
- package/dist/fire-event.js.map +1 -1
- package/dist/frame-sync.d.ts +3 -2
- package/dist/frame-sync.d.ts.map +1 -1
- package/dist/frame-sync.js +19 -9
- package/dist/frame-sync.js.map +1 -1
- package/dist/harness-window.d.ts +5 -0
- package/dist/harness-window.d.ts.map +1 -0
- package/dist/harness-window.js +17 -0
- package/dist/harness-window.js.map +1 -0
- package/dist/index.d.ts +14 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -5
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +5 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +5 -0
- package/dist/internal.js.map +1 -0
- package/dist/matchers.d.ts +88 -46
- package/dist/matchers.d.ts.map +1 -1
- package/dist/matchers.js +178 -20
- package/dist/matchers.js.map +1 -1
- package/dist/pretty-format.d.ts +2 -0
- package/dist/pretty-format.d.ts.map +1 -0
- package/dist/pretty-format.js +2 -0
- package/dist/pretty-format.js.map +1 -0
- package/dist/pretty-widget.d.ts +5 -2
- package/dist/pretty-widget.d.ts.map +1 -1
- package/dist/pretty-widget.js +75 -57
- package/dist/pretty-widget.js.map +1 -1
- package/dist/production.d.ts +8 -0
- package/dist/production.d.ts.map +1 -0
- package/dist/production.js +34 -0
- package/dist/production.js.map +1 -0
- package/dist/queries.d.ts +98 -56
- package/dist/queries.d.ts.map +1 -1
- package/dist/queries.js +123 -83
- package/dist/queries.js.map +1 -1
- package/dist/query-helpers.d.ts +44 -0
- package/dist/query-helpers.d.ts.map +1 -0
- package/dist/query-helpers.js +57 -0
- package/dist/query-helpers.js.map +1 -0
- package/dist/render-children.d.ts +9 -0
- package/dist/render-children.d.ts.map +1 -0
- package/dist/render-children.js +11 -0
- package/dist/render-children.js.map +1 -0
- package/dist/render.d.ts +12 -1
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +52 -16
- package/dist/render.js.map +1 -1
- package/dist/role-helpers.d.ts +12 -3
- package/dist/role-helpers.d.ts.map +1 -1
- package/dist/role-helpers.js +15 -5
- package/dist/role-helpers.js.map +1 -1
- package/dist/role-naming.d.ts +5 -0
- package/dist/role-naming.d.ts.map +1 -0
- package/dist/role-naming.js +96 -0
- package/dist/role-naming.js.map +1 -0
- package/dist/screenshot.d.ts +12 -20
- package/dist/screenshot.d.ts.map +1 -1
- package/dist/screenshot.js +179 -93
- package/dist/screenshot.js.map +1 -1
- package/dist/timers.d.ts +9 -0
- package/dist/timers.d.ts.map +1 -0
- package/dist/timers.js +21 -0
- package/dist/timers.js.map +1 -0
- package/dist/traversal.d.ts +7 -1
- package/dist/traversal.d.ts.map +1 -1
- package/dist/traversal.js +40 -6
- package/dist/traversal.js.map +1 -1
- package/dist/types.d.ts +32 -15
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/user-event/adjustment.d.ts +3 -0
- package/dist/user-event/adjustment.d.ts.map +1 -1
- package/dist/user-event/adjustment.js +25 -3
- package/dist/user-event/adjustment.js.map +1 -1
- package/dist/user-event/click.d.ts +44 -8
- package/dist/user-event/click.d.ts.map +1 -1
- package/dist/user-event/click.js +176 -44
- package/dist/user-event/click.js.map +1 -1
- package/dist/user-event/column-header-click.d.ts +4 -0
- package/dist/user-event/column-header-click.d.ts.map +1 -0
- package/dist/user-event/column-header-click.js +55 -0
- package/dist/user-event/column-header-click.js.map +1 -0
- package/dist/user-event/event-wrapper.d.ts.map +1 -1
- package/dist/user-event/event-wrapper.js +34 -20
- package/dist/user-event/event-wrapper.js.map +1 -1
- package/dist/user-event/index.d.ts +80 -13
- package/dist/user-event/index.d.ts.map +1 -1
- package/dist/user-event/index.js +44 -26
- package/dist/user-event/index.js.map +1 -1
- package/dist/user-event/indexed-children.d.ts +10 -0
- package/dist/user-event/indexed-children.d.ts.map +1 -0
- package/dist/user-event/indexed-children.js +50 -0
- package/dist/user-event/indexed-children.js.map +1 -0
- package/dist/user-event/keyboard.d.ts.map +1 -1
- package/dist/user-event/keyboard.js +115 -31
- package/dist/user-event/keyboard.js.map +1 -1
- package/dist/user-event/list-row-click.d.ts +4 -0
- package/dist/user-event/list-row-click.d.ts.map +1 -0
- package/dist/user-event/list-row-click.js +38 -0
- package/dist/user-event/list-row-click.js.map +1 -0
- package/dist/user-event/native-click.d.ts +6 -0
- package/dist/user-event/native-click.d.ts.map +1 -0
- package/dist/user-event/native-click.js +36 -0
- package/dist/user-event/native-click.js.map +1 -0
- package/dist/user-event/notebook-tab-click.d.ts +5 -0
- package/dist/user-event/notebook-tab-click.d.ts.map +1 -0
- package/dist/user-event/notebook-tab-click.js +39 -0
- package/dist/user-event/notebook-tab-click.js.map +1 -0
- package/dist/user-event/pointer.d.ts +1 -1
- package/dist/user-event/pointer.d.ts.map +1 -1
- package/dist/user-event/pointer.js +33 -9
- package/dist/user-event/pointer.js.map +1 -1
- package/dist/user-event/selection.d.ts +11 -8
- package/dist/user-event/selection.d.ts.map +1 -1
- package/dist/user-event/selection.js +49 -38
- package/dist/user-event/selection.js.map +1 -1
- package/dist/user-event/text.d.ts +12 -5
- package/dist/user-event/text.d.ts.map +1 -1
- package/dist/user-event/text.js +151 -46
- package/dist/user-event/text.js.map +1 -1
- package/dist/wait-for.d.ts.map +1 -1
- package/dist/wait-for.js +4 -3
- package/dist/wait-for.js.map +1 -1
- package/dist/widget-accessible-properties.d.ts +14 -26
- package/dist/widget-accessible-properties.d.ts.map +1 -1
- package/dist/widget-accessible-properties.js +135 -190
- package/dist/widget-accessible-properties.js.map +1 -1
- package/dist/widget-getters.d.ts +11 -0
- package/dist/widget-getters.d.ts.map +1 -0
- package/dist/widget-getters.js +46 -0
- package/dist/widget-getters.js.map +1 -0
- package/dist/window-state.d.ts +10 -0
- package/dist/window-state.d.ts.map +1 -0
- package/dist/window-state.js +41 -0
- package/dist/window-state.js.map +1 -0
- package/dist/within.d.ts +3 -2
- package/dist/within.d.ts.map +1 -1
- package/dist/within.js +3 -2
- package/dist/within.js.map +1 -1
- package/package.json +21 -8
- package/src/accessible-native.ts +333 -0
- package/src/act.ts +1 -1
- package/src/build-queries.ts +47 -41
- package/src/cleanup-registry.ts +1 -1
- package/src/config.ts +10 -1
- package/src/errors.ts +12 -1
- package/src/fire-event.ts +61 -8
- package/src/frame-sync.ts +30 -9
- package/src/harness-window.ts +23 -0
- package/src/index.ts +18 -11
- package/src/internal.ts +12 -0
- package/src/matchers.ts +457 -72
- package/src/pretty-format.ts +1 -0
- package/src/pretty-widget.ts +98 -70
- package/src/production.ts +51 -0
- package/src/queries.ts +127 -89
- package/src/query-helpers.ts +97 -0
- package/src/render-children.ts +25 -0
- package/src/render.tsx +77 -17
- package/src/role-helpers.ts +16 -5
- package/src/role-naming.ts +99 -0
- package/src/screenshot.ts +266 -104
- package/src/timers.ts +31 -0
- package/src/traversal.ts +66 -6
- package/src/types.ts +34 -17
- package/src/user-event/adjustment.ts +31 -3
- package/src/user-event/click.ts +248 -52
- package/src/user-event/column-header-click.ts +76 -0
- package/src/user-event/event-wrapper.ts +41 -23
- package/src/user-event/index.ts +130 -40
- package/src/user-event/indexed-children.ts +75 -0
- package/src/user-event/keyboard.ts +161 -43
- package/src/user-event/list-row-click.ts +54 -0
- package/src/user-event/native-click.ts +51 -0
- package/src/user-event/notebook-tab-click.ts +57 -0
- package/src/user-event/pointer.ts +48 -9
- package/src/user-event/selection.ts +67 -41
- package/src/user-event/text.ts +192 -46
- package/src/wait-for.ts +4 -4
- package/src/widget-accessible-properties.ts +183 -230
- package/src/widget-getters.ts +85 -0
- package/src/window-state.ts +70 -0
- package/src/within.ts +3 -2
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { camelCase } from "@gtkx/utils";
|
|
2
|
+
import { buildQueries } from "./build-queries.js";
|
|
3
|
+
import { getElementError } from "./errors.js";
|
|
4
|
+
import { isMatchingWidgetType, isTextMatch } from "./queries.js";
|
|
5
|
+
import { findAll } from "./traversal.js";
|
|
6
|
+
/** The query-building helpers, bundled so they can be reached under a single import. */
|
|
7
|
+
const queryHelpers = {
|
|
8
|
+
buildQueries,
|
|
9
|
+
getElementError,
|
|
10
|
+
queryAllByObjectProperty,
|
|
11
|
+
queryByObjectProperty,
|
|
12
|
+
};
|
|
13
|
+
const readObjectProperty = (widget, property) => {
|
|
14
|
+
const value = Reflect.get(widget, camelCase(property));
|
|
15
|
+
if (typeof value === "string") {
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
|
|
19
|
+
return String(value);
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Finds every widget carrying a GObject property whose value matches, the counterpart of DOM Testing
|
|
25
|
+
* Library's `queryAllByAttribute`. The property name may be given in kebab-case or camelCase, and
|
|
26
|
+
* widgets that are not mapped are never matched.
|
|
27
|
+
*
|
|
28
|
+
* @param property Name of the GObject property to read.
|
|
29
|
+
* @param container Widget subtree to search.
|
|
30
|
+
* @param text Matcher for the property's value.
|
|
31
|
+
* @param options Text matching options.
|
|
32
|
+
* @returns Every matching widget, or an empty array when none match.
|
|
33
|
+
*/
|
|
34
|
+
function queryAllByObjectProperty(property, container, text, options) {
|
|
35
|
+
return findAll(container, (widget) => isMatchingWidgetType(widget, options) &&
|
|
36
|
+
isTextMatch(readObjectProperty(widget, property), text, widget, options));
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Returns the single widget carrying a GObject property whose value matches, or null when none do,
|
|
40
|
+
* the counterpart of DOM Testing Library's `queryByAttribute`.
|
|
41
|
+
*
|
|
42
|
+
* @param property Name of the GObject property to read.
|
|
43
|
+
* @param container Widget subtree to search.
|
|
44
|
+
* @param text Matcher for the property's value.
|
|
45
|
+
* @param options Text matching options.
|
|
46
|
+
* @returns The matching widget, or null when none match.
|
|
47
|
+
* @throws When more than one widget matches.
|
|
48
|
+
*/
|
|
49
|
+
function queryByObjectProperty(property, container, text, options) {
|
|
50
|
+
const matches = queryAllByObjectProperty(property, container, text, options);
|
|
51
|
+
if (matches.length > 1) {
|
|
52
|
+
throw getElementError(`Found ${String(matches.length)} elements with the '${property}' property, but expected only one`, container);
|
|
53
|
+
}
|
|
54
|
+
return matches[0] ?? null;
|
|
55
|
+
}
|
|
56
|
+
export { queryAllByObjectProperty, queryByObjectProperty, queryHelpers };
|
|
57
|
+
//# sourceMappingURL=query-helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-helpers.js","sourceRoot":"","sources":["../src/query-helpers.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAkB,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAczD,wFAAwF;AACxF,MAAM,YAAY,GAAiB;IAC/B,YAAY;IACZ,eAAe;IACf,wBAAwB;IACxB,qBAAqB;CACxB,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,MAAkB,EAAE,QAAgB,EAAiB,EAAE;IAC/E,MAAM,KAAK,GAAY,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEhE,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvF,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,SAAS,wBAAwB,CAC7B,QAAgB,EAChB,SAAoB,EACpB,IAAa,EACb,OAAwB;IAExB,OAAO,OAAO,CACV,SAAS,EACT,CAAC,MAAM,EAAE,EAAE,CACP,oBAAoB,CAAC,MAAM,EAAE,OAAO,CAAC;QACrC,WAAW,CAAC,kBAAkB,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAC/E,CAAC;AACN,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAS,qBAAqB,CAC1B,QAAgB,EAChB,SAAoB,EACpB,IAAa,EACb,OAAwB;IAExB,MAAM,OAAO,GAAG,wBAAwB,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAE7E,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,eAAe,CACjB,SAAS,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,uBAAuB,QAAQ,mCAAmC,EACjG,SAAS,CACZ,CAAC;IACN,CAAC;IAED,OAAO,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AAC9B,CAAC;AAED,OAAO,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,YAAY,EAAqB,CAAC","sourcesContent":["import type * as Gtk from \"@gtkx/gi/gtk\";\nimport { camelCase } from \"@gtkx/utils\";\nimport type { Matcher, MatcherOptions } from \"./types.js\";\nimport { buildQueries } from \"./build-queries.js\";\nimport { getElementError } from \"./errors.js\";\nimport { isMatchingWidgetType, isTextMatch } from \"./queries.js\";\nimport { type Container, findAll } from \"./traversal.js\";\n\n/** The helpers used to build custom queries, bundled the way DOM Testing Library exposes them. */\ntype QueryHelpers = {\n /** Derives a query family's variants from its `queryAllBy` function. */\n buildQueries: typeof buildQueries;\n /** Builds the error a failing query throws. */\n getElementError: typeof getElementError;\n /** Finds every widget whose GObject property matches. */\n queryAllByObjectProperty: typeof queryAllByObjectProperty;\n /** Finds the single widget whose GObject property matches. */\n queryByObjectProperty: typeof queryByObjectProperty;\n};\n\n/** The query-building helpers, bundled so they can be reached under a single import. */\nconst queryHelpers: QueryHelpers = {\n buildQueries,\n getElementError,\n queryAllByObjectProperty,\n queryByObjectProperty,\n};\n\nconst readObjectProperty = (widget: Gtk.Widget, property: string): string | null => {\n const value: unknown = Reflect.get(widget, camelCase(property));\n\n if (typeof value === \"string\") {\n return value;\n }\n\n if (typeof value === \"number\" || typeof value === \"boolean\" || typeof value === \"bigint\") {\n return String(value);\n }\n\n return null;\n};\n\n/**\n * Finds every widget carrying a GObject property whose value matches, the counterpart of DOM Testing\n * Library's `queryAllByAttribute`. The property name may be given in kebab-case or camelCase, and\n * widgets that are not mapped are never matched.\n *\n * @param property Name of the GObject property to read.\n * @param container Widget subtree to search.\n * @param text Matcher for the property's value.\n * @param options Text matching options.\n * @returns Every matching widget, or an empty array when none match.\n */\nfunction queryAllByObjectProperty(\n property: string,\n container: Container,\n text: Matcher,\n options?: MatcherOptions,\n): Gtk.Widget[] {\n return findAll(\n container,\n (widget) =>\n isMatchingWidgetType(widget, options) &&\n isTextMatch(readObjectProperty(widget, property), text, widget, options),\n );\n}\n\n/**\n * Returns the single widget carrying a GObject property whose value matches, or null when none do,\n * the counterpart of DOM Testing Library's `queryByAttribute`.\n *\n * @param property Name of the GObject property to read.\n * @param container Widget subtree to search.\n * @param text Matcher for the property's value.\n * @param options Text matching options.\n * @returns The matching widget, or null when none match.\n * @throws When more than one widget matches.\n */\nfunction queryByObjectProperty(\n property: string,\n container: Container,\n text: Matcher,\n options?: MatcherOptions,\n): Gtk.Widget | null {\n const matches = queryAllByObjectProperty(property, container, text, options);\n\n if (matches.length > 1) {\n throw getElementError(\n `Found ${String(matches.length)} elements with the '${property}' property, but expected only one`,\n container,\n );\n }\n\n return matches[0] ?? null;\n}\n\nexport { queryAllByObjectProperty, queryByObjectProperty, queryHelpers, type QueryHelpers };\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { RenderOptions } from "./types.js";
|
|
3
|
+
type ChildrenBuilder<T> = (items: T[]) => ReactNode;
|
|
4
|
+
type RenderChildrenResult<T> = {
|
|
5
|
+
rerender: (items: T[]) => Promise<void>;
|
|
6
|
+
};
|
|
7
|
+
declare function renderChildren<T>(initial: T[], build: ChildrenBuilder<T>, options?: RenderOptions): Promise<RenderChildrenResult<T>>;
|
|
8
|
+
export { renderChildren, type ChildrenBuilder };
|
|
9
|
+
//# sourceMappingURL=render-children.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-children.d.ts","sourceRoot":"","sources":["../src/render-children.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGhD,KAAK,eAAe,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,SAAS,CAAC;AAEpD,KAAK,oBAAoB,CAAC,CAAC,IAAI;IAC3B,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C,CAAC;AAEF,iBAAe,cAAc,CAAC,CAAC,EAC3B,OAAO,EAAE,CAAC,EAAE,EACZ,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,EACzB,OAAO,CAAC,EAAE,aAAa,GACxB,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAQlC;AAED,OAAO,EAAE,cAAc,EAAE,KAAK,eAAe,EAAE,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { render } from "./render.js";
|
|
2
|
+
async function renderChildren(initial, build, options) {
|
|
3
|
+
const { rerender } = await render(build(initial), options);
|
|
4
|
+
return {
|
|
5
|
+
rerender: async (items) => {
|
|
6
|
+
await rerender(build(items));
|
|
7
|
+
},
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export { renderChildren };
|
|
11
|
+
//# sourceMappingURL=render-children.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-children.js","sourceRoot":"","sources":["../src/render-children.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAQrC,KAAK,UAAU,cAAc,CACzB,OAAY,EACZ,KAAyB,EACzB,OAAuB;IAEvB,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;IAE3D,OAAO;QACH,QAAQ,EAAE,KAAK,EAAE,KAAU,EAAE,EAAE;YAC3B,MAAM,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;QACjC,CAAC;KACJ,CAAC;AACN,CAAC;AAED,OAAO,EAAE,cAAc,EAAwB,CAAC","sourcesContent":["import type { ReactNode } from \"react\";\nimport type { RenderOptions } from \"./types.js\";\nimport { render } from \"./render.js\";\n\ntype ChildrenBuilder<T> = (items: T[]) => ReactNode;\n\ntype RenderChildrenResult<T> = {\n rerender: (items: T[]) => Promise<void>;\n};\n\nasync function renderChildren<T>(\n initial: T[],\n build: ChildrenBuilder<T>,\n options?: RenderOptions,\n): Promise<RenderChildrenResult<T>> {\n const { rerender } = await render(build(initial), options);\n\n return {\n rerender: async (items: T[]) => {\n await rerender(build(items));\n },\n };\n}\n\nexport { renderChildren, type ChildrenBuilder };\n"]}
|
package/dist/render.d.ts
CHANGED
|
@@ -4,11 +4,22 @@ import type { QueryMap, RenderOptions } from "./types.js";
|
|
|
4
4
|
/**
|
|
5
5
|
* Renders a React element into a GTK4 widget tree and returns queries
|
|
6
6
|
* scoped to it along with controls for rerendering and unmounting. When no
|
|
7
|
-
* container is supplied, a harness window is created and presented
|
|
7
|
+
* container is supplied, a harness window is created and presented, and the editable it hands the
|
|
8
|
+
* focus to keeps its text unselected, with its caret at the end. The returned promise settles once
|
|
9
|
+
* the window the tree is shown in has been laid out and activation has arrived, so platform state
|
|
10
|
+
* such as focus is already readable when it resolves. A presented harness window is waited on until
|
|
11
|
+
* it is itself active; a window the caller or the tree owns is waited on until the application holds
|
|
12
|
+
* activation, since only a present can claim it. Rendering into a container that is not shown waits
|
|
13
|
+
* for nothing, and a window that never becomes readable within `windowActivationTimeout` throws an
|
|
14
|
+
* error naming the condition that failed rather than resolving with unreadable platform state. A
|
|
15
|
+
* tree mounted into a container that sits outside every toplevel, or inside a window that is not
|
|
16
|
+
* visible, is out of reach of a pointer and a keyboard, so every `userEvent` helper aimed at it
|
|
17
|
+
* rejects after `actionabilityTimeout` naming that condition, and `fireEvent` drives it instead.
|
|
8
18
|
*
|
|
9
19
|
* @param element The React element to render.
|
|
10
20
|
* @param options Optional container, wrapper, custom queries, and other render settings.
|
|
11
21
|
* @returns A render result with bound queries, debug helpers, and lifecycle controls.
|
|
22
|
+
* @throws When the window the tree is shown in is not laid out and activated in time.
|
|
12
23
|
*/
|
|
13
24
|
declare const render: <Q extends QueryMap = Record<never, never>>(element: ReactNode, options?: RenderOptions<Q>) => Promise<RenderResult<Q>>;
|
|
14
25
|
/**
|
package/dist/render.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.tsx"],"names":[],"mappings":"AASA,OAAO,EAAkB,KAAK,SAAS,EAAc,MAAM,OAAO,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAqB,MAAM,YAAY,CAAC;AAgM7E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,QAAA,MAAM,MAAM,GAAU,CAAC,SAAS,QAAQ,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAC3D,SAAS,SAAS,EAClB,UAAU,aAAa,CAAC,CAAC,CAAC,KAC3B,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAoDzB,CAAC;AAEF;;;GAGG;AACH,QAAA,MAAM,OAAO,QAAa,OAAO,CAAC,IAAI,CAErC,CAAC;AAEF,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC"}
|
package/dist/render.js
CHANGED
|
@@ -1,24 +1,34 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import * as Gtk from "@gtkx/gi/gtk";
|
|
3
|
-
import { createReconcilerRoot, isRootElement, setReconcilerErrorHandler, } from "@gtkx/react/internal";
|
|
3
|
+
import { createReconcilerRoot, isRootElement, setReconcilerErrorHandler, settleAccessible, } from "@gtkx/react/internal";
|
|
4
4
|
import { StrictMode } from "react";
|
|
5
5
|
import { runInAct } from "./act.js";
|
|
6
6
|
import { addToCleanupQueue, runCleanup } from "./cleanup-registry.js";
|
|
7
|
-
import {
|
|
7
|
+
import { getConfig } from "./config.js";
|
|
8
|
+
import { scheduleWhenWindowReady } from "./frame-sync.js";
|
|
9
|
+
import { createHarnessWindow, presentHarnessWindow } from "./harness-window.js";
|
|
8
10
|
import { logWidget } from "./pretty-widget.js";
|
|
9
11
|
import { logRoles } from "./role-helpers.js";
|
|
10
12
|
import { clearScreen, setScreen } from "./screen.js";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
+
import { captureScreen } from "./screenshot.js";
|
|
14
|
+
import { roots, TOPLEVELS } from "./traversal.js";
|
|
13
15
|
import { resetClipboard } from "./user-event/index.js";
|
|
16
|
+
import { findPresentedWindowFailure, findRenderedWindowFailure, mappedToplevels } from "./window-state.js";
|
|
14
17
|
import { within } from "./within.js";
|
|
15
18
|
const reconcilerErrors = { lastError: null, isHandlerInstalled: false };
|
|
16
19
|
const activeRenders = new Set();
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
});
|
|
20
|
+
const settleWindow = async (window, findFailure, action) => {
|
|
21
|
+
const timeout = getConfig().windowActivationTimeout;
|
|
22
|
+
await new Promise((resolve) => {
|
|
23
|
+
scheduleWhenWindowReady(window, (target) => findFailure(target) === null, timeout, resolve);
|
|
24
|
+
});
|
|
25
|
+
settleAccessible();
|
|
26
|
+
const failure = window === null ? null : findFailure(window);
|
|
27
|
+
if (failure !== null) {
|
|
28
|
+
throw new Error(`${action} timed out after ${String(timeout)}ms waiting for the window it rendered into: ${failure}. ` +
|
|
29
|
+
"Platform state such as focus is only readable once that window is allocated and active.");
|
|
30
|
+
}
|
|
31
|
+
};
|
|
22
32
|
const update = async (element, root) => {
|
|
23
33
|
await runInAct(() => {
|
|
24
34
|
root.update(element);
|
|
@@ -60,7 +70,7 @@ const resolveContainer = (container) => {
|
|
|
60
70
|
if (container instanceof Gtk.Widget) {
|
|
61
71
|
return { containerInfo: container, window: null };
|
|
62
72
|
}
|
|
63
|
-
const window =
|
|
73
|
+
const window = createHarnessWindow();
|
|
64
74
|
window.setDecorated(false);
|
|
65
75
|
return { containerInfo: window, window };
|
|
66
76
|
};
|
|
@@ -68,7 +78,7 @@ const firstToplevelWidget = (baseElement) => {
|
|
|
68
78
|
if (baseElement instanceof Gtk.Widget) {
|
|
69
79
|
return baseElement;
|
|
70
80
|
}
|
|
71
|
-
const [first] =
|
|
81
|
+
const [first] = roots(baseElement);
|
|
72
82
|
if (first) {
|
|
73
83
|
return first;
|
|
74
84
|
}
|
|
@@ -83,6 +93,21 @@ const resolveResultContainer = (resolved, container, baseElement) => {
|
|
|
83
93
|
}
|
|
84
94
|
return firstToplevelWidget(baseElement);
|
|
85
95
|
};
|
|
96
|
+
const realizedWindow = (root) => root instanceof Gtk.Window && root.getFrameClock() !== null ? root : null;
|
|
97
|
+
const settleTarget = (resolved, container) => {
|
|
98
|
+
if (resolved.window) {
|
|
99
|
+
return realizedWindow(resolved.window);
|
|
100
|
+
}
|
|
101
|
+
if (container instanceof Gtk.Widget) {
|
|
102
|
+
return realizedWindow(container.getRoot());
|
|
103
|
+
}
|
|
104
|
+
return realizedWindow(mappedToplevels()[0] ?? null);
|
|
105
|
+
};
|
|
106
|
+
const settleRender = async (resolved, container, action) => {
|
|
107
|
+
const isPresentedNow = action === "render" && resolved.window !== null;
|
|
108
|
+
const findFailure = isPresentedNow ? findPresentedWindowFailure : findRenderedWindowFailure;
|
|
109
|
+
await settleWindow(settleTarget(resolved, container), findFailure, action);
|
|
110
|
+
};
|
|
86
111
|
const renderErrorHandlers = (options) => ({
|
|
87
112
|
onUncaughtError: handleError,
|
|
88
113
|
onCaughtError: (error, errorInfo) => {
|
|
@@ -102,11 +127,22 @@ const applyEnableAnimations = (areAnimationsEnabled) => {
|
|
|
102
127
|
/**
|
|
103
128
|
* Renders a React element into a GTK4 widget tree and returns queries
|
|
104
129
|
* scoped to it along with controls for rerendering and unmounting. When no
|
|
105
|
-
* container is supplied, a harness window is created and presented
|
|
130
|
+
* container is supplied, a harness window is created and presented, and the editable it hands the
|
|
131
|
+
* focus to keeps its text unselected, with its caret at the end. The returned promise settles once
|
|
132
|
+
* the window the tree is shown in has been laid out and activation has arrived, so platform state
|
|
133
|
+
* such as focus is already readable when it resolves. A presented harness window is waited on until
|
|
134
|
+
* it is itself active; a window the caller or the tree owns is waited on until the application holds
|
|
135
|
+
* activation, since only a present can claim it. Rendering into a container that is not shown waits
|
|
136
|
+
* for nothing, and a window that never becomes readable within `windowActivationTimeout` throws an
|
|
137
|
+
* error naming the condition that failed rather than resolving with unreadable platform state. A
|
|
138
|
+
* tree mounted into a container that sits outside every toplevel, or inside a window that is not
|
|
139
|
+
* visible, is out of reach of a pointer and a keyboard, so every `userEvent` helper aimed at it
|
|
140
|
+
* rejects after `actionabilityTimeout` naming that condition, and `fireEvent` drives it instead.
|
|
106
141
|
*
|
|
107
142
|
* @param element The React element to render.
|
|
108
143
|
* @param options Optional container, wrapper, custom queries, and other render settings.
|
|
109
144
|
* @returns A render result with bound queries, debug helpers, and lifecycle controls.
|
|
145
|
+
* @throws When the window the tree is shown in is not laid out and activated in time.
|
|
110
146
|
*/
|
|
111
147
|
const render = async (element, options) => {
|
|
112
148
|
installErrorHandler();
|
|
@@ -128,8 +164,8 @@ const render = async (element, options) => {
|
|
|
128
164
|
return options?.isReactStrictMode ? _jsx(StrictMode, { children: wrapped }) : wrapped;
|
|
129
165
|
};
|
|
130
166
|
await update(wrap(element), root);
|
|
131
|
-
resolved.window
|
|
132
|
-
await
|
|
167
|
+
presentHarnessWindow(resolved.window);
|
|
168
|
+
await settleRender(resolved, options?.container, "render");
|
|
133
169
|
const container = resolveResultContainer(resolved, options?.container, baseElement);
|
|
134
170
|
const result = {
|
|
135
171
|
...within(baseElement, options?.queries),
|
|
@@ -140,7 +176,7 @@ const render = async (element, options) => {
|
|
|
140
176
|
},
|
|
141
177
|
rerender: async (newElement) => {
|
|
142
178
|
await update(wrap(newElement), root);
|
|
143
|
-
await
|
|
179
|
+
await settleRender(resolved, options?.container, "rerender");
|
|
144
180
|
},
|
|
145
181
|
debug: (element = baseElement, debugOptions) => {
|
|
146
182
|
logWidget(element, debugOptions);
|
|
@@ -148,7 +184,7 @@ const render = async (element, options) => {
|
|
|
148
184
|
logRoles: () => {
|
|
149
185
|
logRoles(baseElement);
|
|
150
186
|
},
|
|
151
|
-
screenshot: (
|
|
187
|
+
screenshot: (screenshotOptions) => captureScreen(screenshotOptions),
|
|
152
188
|
};
|
|
153
189
|
setScreen(result);
|
|
154
190
|
return result;
|
package/dist/render.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { RootElement } from \"@gtkx/react\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport {\n createReconcilerRoot,\n isRootElement,\n type ReconcilerRoot,\n setReconcilerErrorHandler,\n} from \"@gtkx/react/internal\";\nimport { type ErrorInfo, type ReactNode, StrictMode } from \"react\";\nimport type { RenderResult } from \"./bound-queries.js\";\nimport type { QueryMap, RenderOptions, ScreenshotOptions, WindowSelector } from \"./types.js\";\nimport { runInAct } from \"./act.js\";\nimport { addToCleanupQueue, runCleanup } from \"./cleanup-registry.js\";\nimport { scheduleAfterLayout } from \"./frame-sync.js\";\nimport { logWidget, type PrettyWidgetOptions } from \"./pretty-widget.js\";\nimport { logRoles } from \"./role-helpers.js\";\nimport { clearScreen, setScreen } from \"./screen.js\";\nimport { captureAndSaveScreenshot } from \"./screenshot.js\";\nimport { type Container, TOPLEVELS, traverse } from \"./traversal.js\";\nimport { resetClipboard } from \"./user-event/index.js\";\nimport { within } from \"./within.js\";\n\ntype ActiveRender = {\n root: ReconcilerRoot;\n window: Gtk.Window | null;\n};\n\ntype ResolvedContainer = {\n containerInfo: Gtk.Widget | RootElement;\n window: Gtk.Window | null;\n};\n\ntype ReconcilerErrorState = {\n lastError: Error | null;\n isHandlerInstalled: boolean;\n};\n\nconst reconcilerErrors: ReconcilerErrorState = { lastError: null, isHandlerInstalled: false };\nconst activeRenders: Set<ActiveRender> = new Set();\nconst HARNESS_WINDOW_WIDTH = 800;\nconst HARNESS_WINDOW_HEIGHT = 600;\n\nconst flushLayout = (window: Gtk.Window | null): Promise<void> =>\n new Promise((resolve) => {\n scheduleAfterLayout(window, resolve);\n });\n\nconst update = async (element: ReactNode, root: ReconcilerRoot): Promise<void> => {\n await runInAct(() => {\n root.update(element);\n });\n\n if (reconcilerErrors.lastError) {\n const captured = reconcilerErrors.lastError;\n reconcilerErrors.lastError = null;\n throw captured;\n }\n};\n\nconst disposeActiveRender = async (active: ActiveRender): Promise<void> => {\n if (!activeRenders.delete(active)) {\n return;\n }\n\n await active.root.unmount(async (root) => {\n await update(null, root);\n active.window?.destroy();\n });\n};\n\nconst disposeAllActiveRenders = async (): Promise<void> => {\n for (const active of activeRenders) {\n await disposeActiveRender(active);\n }\n};\n\nconst handleError = (error: unknown): void => {\n reconcilerErrors.lastError = error instanceof Error ? error : new Error(String(error));\n};\n\nconst installErrorHandler = (): void => {\n if (reconcilerErrors.isHandlerInstalled) {\n return;\n }\n\n setReconcilerErrorHandler(handleError);\n reconcilerErrors.isHandlerInstalled = true;\n};\n\nconst resolveContainer = (container: RenderOptions[\"container\"]): ResolvedContainer => {\n if (isRootElement(container)) {\n return { containerInfo: container, window: null };\n }\n\n if (container instanceof Gtk.Widget) {\n return { containerInfo: container, window: null };\n }\n\n const window = new Gtk.Window({ defaultWidth: HARNESS_WINDOW_WIDTH, defaultHeight: HARNESS_WINDOW_HEIGHT });\n window.setDecorated(false);\n\n return { containerInfo: window, window };\n};\n\nconst firstToplevelWidget = (baseElement: Container): Gtk.Widget => {\n if (baseElement instanceof Gtk.Widget) {\n return baseElement;\n }\n\n const [first] = traverse(baseElement);\n\n if (first) {\n return first;\n }\n\n throw new Error(\"render() produced no widgets: ensure the element renders visible content\");\n};\n\nconst resolveResultContainer = (\n resolved: ResolvedContainer,\n container: RenderOptions[\"container\"],\n baseElement: Container,\n): Gtk.Widget => {\n if (resolved.window) {\n return resolved.window;\n }\n\n if (container instanceof Gtk.Widget) {\n return container;\n }\n\n return firstToplevelWidget(baseElement);\n};\n\nconst renderErrorHandlers = <Q extends QueryMap>(options: RenderOptions<Q> | undefined) => ({\n onUncaughtError: handleError,\n onCaughtError: (error: unknown, errorInfo: ErrorInfo): void => {\n handleError(error);\n options?.onCaughtError?.(error, errorInfo);\n },\n onRecoverableError: (error: unknown, errorInfo: ErrorInfo): void => {\n options?.onRecoverableError?.(error, errorInfo);\n },\n});\n\nconst applyEnableAnimations = (areAnimationsEnabled: boolean): void => {\n const settings = Gtk.Settings.getDefault();\n\n if (settings) {\n settings.gtkEnableAnimations = areAnimationsEnabled;\n }\n};\n\n/**\n * Renders a React element into a GTK4 widget tree and returns queries\n * scoped to it along with controls for rerendering and unmounting. When no\n * container is supplied, a harness window is created and presented.\n *\n * @param element The React element to render.\n * @param options Optional container, wrapper, custom queries, and other render settings.\n * @returns A render result with bound queries, debug helpers, and lifecycle controls.\n */\nconst render = async <Q extends QueryMap = Record<never, never>>(\n element: ReactNode,\n options?: RenderOptions<Q>,\n): Promise<RenderResult<Q>> => {\n installErrorHandler();\n applyEnableAnimations(options?.areAnimationsEnabled === true);\n const baseElement: Container = options?.baseElement ?? TOPLEVELS;\n const Wrapper = options?.wrapper;\n const resolved = resolveContainer(options?.container);\n\n const root = createReconcilerRoot({\n containerInfo: resolved.containerInfo,\n ...renderErrorHandlers(options),\n });\n\n const active: ActiveRender = { root, window: resolved.window };\n activeRenders.add(active);\n addToCleanupQueue(disposeAllActiveRenders);\n addToCleanupQueue(clearScreen);\n addToCleanupQueue(resetClipboard);\n\n const wrap = (node: ReactNode): ReactNode => {\n const wrapped = Wrapper ? <Wrapper>{node}</Wrapper> : node;\n\n return options?.isReactStrictMode ? <StrictMode>{wrapped}</StrictMode> : wrapped;\n };\n\n await update(wrap(element), root);\n resolved.window?.present();\n await flushLayout(resolved.window);\n const container = resolveResultContainer(resolved, options?.container, baseElement);\n\n const result: RenderResult<Q> = {\n ...within(baseElement, options?.queries),\n container,\n baseElement,\n unmount: async () => {\n await disposeActiveRender(active);\n },\n rerender: async (newElement: ReactNode) => {\n await update(wrap(newElement), root);\n await flushLayout(resolved.window);\n },\n debug: (element: Container | Container[] = baseElement, debugOptions?: PrettyWidgetOptions) => {\n logWidget(element, debugOptions);\n },\n logRoles: () => {\n logRoles(baseElement);\n },\n screenshot: (selector?: WindowSelector, screenshotOptions?: ScreenshotOptions) =>\n captureAndSaveScreenshot(selector, screenshotOptions),\n };\n\n setScreen(result);\n\n return result;\n};\n\n/**\n * Unmounts every active render and runs all registered cleanup callbacks,\n * resetting the screen and clipboard. Called automatically after each test.\n */\nconst cleanup = async (): Promise<void> => {\n await runCleanup();\n};\n\nexport { render, cleanup };\n"]}
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { RootElement } from \"@gtkx/react\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport {\n createReconcilerRoot,\n isRootElement,\n type ReconcilerRoot,\n setReconcilerErrorHandler,\n settleAccessible,\n} from \"@gtkx/react/internal\";\nimport { type ErrorInfo, type ReactNode, StrictMode } from \"react\";\nimport type { RenderResult } from \"./bound-queries.js\";\nimport type { QueryMap, RenderOptions, ScreenshotOptions } from \"./types.js\";\nimport { runInAct } from \"./act.js\";\nimport { addToCleanupQueue, runCleanup } from \"./cleanup-registry.js\";\nimport { getConfig } from \"./config.js\";\nimport { scheduleWhenWindowReady } from \"./frame-sync.js\";\nimport { createHarnessWindow, presentHarnessWindow } from \"./harness-window.js\";\nimport { logWidget, type PrettyWidgetOptions } from \"./pretty-widget.js\";\nimport { logRoles } from \"./role-helpers.js\";\nimport { clearScreen, setScreen } from \"./screen.js\";\nimport { captureScreen } from \"./screenshot.js\";\nimport { type Container, roots, TOPLEVELS } from \"./traversal.js\";\nimport { resetClipboard } from \"./user-event/index.js\";\nimport { findPresentedWindowFailure, findRenderedWindowFailure, mappedToplevels } from \"./window-state.js\";\nimport { within } from \"./within.js\";\n\n/** A mounted render tracked so cleanup can unmount it. */\ntype ActiveRender = {\n /** Root that rerenders drive and that cleanup tears the tree down through. */\n root: ReconcilerRoot;\n /** Harness window created for the render, null when it renders into a container the caller supplied. */\n window: Gtk.Window | null;\n};\n\ntype ResolvedContainer = {\n containerInfo: Gtk.Widget | RootElement;\n window: Gtk.Window | null;\n};\n\ntype ReconcilerErrorState = {\n lastError: Error | null;\n isHandlerInstalled: boolean;\n};\n\ntype WindowFailureReporter = (window: Gtk.Window) => string | null;\ntype SettleAction = \"render\" | \"rerender\";\n\nconst reconcilerErrors: ReconcilerErrorState = { lastError: null, isHandlerInstalled: false };\nconst activeRenders: Set<ActiveRender> = new Set();\n\nconst settleWindow = async (\n window: Gtk.Window | null,\n findFailure: WindowFailureReporter,\n action: SettleAction,\n): Promise<void> => {\n const timeout = getConfig().windowActivationTimeout;\n\n await new Promise<void>((resolve) => {\n scheduleWhenWindowReady(window, (target) => findFailure(target) === null, timeout, resolve);\n });\n\n settleAccessible();\n const failure = window === null ? null : findFailure(window);\n\n if (failure !== null) {\n throw new Error(\n `${action} timed out after ${String(timeout)}ms waiting for the window it rendered into: ${failure}. ` +\n \"Platform state such as focus is only readable once that window is allocated and active.\",\n );\n }\n};\n\nconst update = async (element: ReactNode, root: ReconcilerRoot): Promise<void> => {\n await runInAct(() => {\n root.update(element);\n });\n\n if (reconcilerErrors.lastError) {\n const captured = reconcilerErrors.lastError;\n reconcilerErrors.lastError = null;\n throw captured;\n }\n};\n\nconst disposeActiveRender = async (active: ActiveRender): Promise<void> => {\n if (!activeRenders.delete(active)) {\n return;\n }\n\n await active.root.unmount(async (root) => {\n await update(null, root);\n active.window?.destroy();\n });\n};\n\nconst disposeAllActiveRenders = async (): Promise<void> => {\n for (const active of activeRenders) {\n await disposeActiveRender(active);\n }\n};\n\nconst handleError = (error: unknown): void => {\n reconcilerErrors.lastError = error instanceof Error ? error : new Error(String(error));\n};\n\nconst installErrorHandler = (): void => {\n if (reconcilerErrors.isHandlerInstalled) {\n return;\n }\n\n setReconcilerErrorHandler(handleError);\n reconcilerErrors.isHandlerInstalled = true;\n};\n\nconst resolveContainer = (container: RenderOptions[\"container\"]): ResolvedContainer => {\n if (isRootElement(container)) {\n return { containerInfo: container, window: null };\n }\n\n if (container instanceof Gtk.Widget) {\n return { containerInfo: container, window: null };\n }\n\n const window = createHarnessWindow();\n window.setDecorated(false);\n\n return { containerInfo: window, window };\n};\n\nconst firstToplevelWidget = (baseElement: Container): Gtk.Widget => {\n if (baseElement instanceof Gtk.Widget) {\n return baseElement;\n }\n\n const [first] = roots(baseElement);\n\n if (first) {\n return first;\n }\n\n throw new Error(\"render() produced no widgets: ensure the element renders visible content\");\n};\n\nconst resolveResultContainer = (\n resolved: ResolvedContainer,\n container: RenderOptions[\"container\"],\n baseElement: Container,\n): Gtk.Widget => {\n if (resolved.window) {\n return resolved.window;\n }\n\n if (container instanceof Gtk.Widget) {\n return container;\n }\n\n return firstToplevelWidget(baseElement);\n};\n\nconst realizedWindow = (root: Gtk.Root | null): Gtk.Window | null =>\n root instanceof Gtk.Window && root.getFrameClock() !== null ? root : null;\n\nconst settleTarget = (resolved: ResolvedContainer, container: RenderOptions[\"container\"]): Gtk.Window | null => {\n if (resolved.window) {\n return realizedWindow(resolved.window);\n }\n\n if (container instanceof Gtk.Widget) {\n return realizedWindow(container.getRoot());\n }\n\n return realizedWindow(mappedToplevels()[0] ?? null);\n};\n\nconst settleRender = async (\n resolved: ResolvedContainer,\n container: RenderOptions[\"container\"],\n action: SettleAction,\n): Promise<void> => {\n const isPresentedNow = action === \"render\" && resolved.window !== null;\n const findFailure = isPresentedNow ? findPresentedWindowFailure : findRenderedWindowFailure;\n await settleWindow(settleTarget(resolved, container), findFailure, action);\n};\n\nconst renderErrorHandlers = <Q extends QueryMap>(options: RenderOptions<Q> | undefined) => ({\n onUncaughtError: handleError,\n onCaughtError: (error: unknown, errorInfo: ErrorInfo): void => {\n handleError(error);\n options?.onCaughtError?.(error, errorInfo);\n },\n onRecoverableError: (error: unknown, errorInfo: ErrorInfo): void => {\n options?.onRecoverableError?.(error, errorInfo);\n },\n});\n\nconst applyEnableAnimations = (areAnimationsEnabled: boolean): void => {\n const settings = Gtk.Settings.getDefault();\n\n if (settings) {\n settings.gtkEnableAnimations = areAnimationsEnabled;\n }\n};\n\n/**\n * Renders a React element into a GTK4 widget tree and returns queries\n * scoped to it along with controls for rerendering and unmounting. When no\n * container is supplied, a harness window is created and presented, and the editable it hands the\n * focus to keeps its text unselected, with its caret at the end. The returned promise settles once\n * the window the tree is shown in has been laid out and activation has arrived, so platform state\n * such as focus is already readable when it resolves. A presented harness window is waited on until\n * it is itself active; a window the caller or the tree owns is waited on until the application holds\n * activation, since only a present can claim it. Rendering into a container that is not shown waits\n * for nothing, and a window that never becomes readable within `windowActivationTimeout` throws an\n * error naming the condition that failed rather than resolving with unreadable platform state. A\n * tree mounted into a container that sits outside every toplevel, or inside a window that is not\n * visible, is out of reach of a pointer and a keyboard, so every `userEvent` helper aimed at it\n * rejects after `actionabilityTimeout` naming that condition, and `fireEvent` drives it instead.\n *\n * @param element The React element to render.\n * @param options Optional container, wrapper, custom queries, and other render settings.\n * @returns A render result with bound queries, debug helpers, and lifecycle controls.\n * @throws When the window the tree is shown in is not laid out and activated in time.\n */\nconst render = async <Q extends QueryMap = Record<never, never>>(\n element: ReactNode,\n options?: RenderOptions<Q>,\n): Promise<RenderResult<Q>> => {\n installErrorHandler();\n applyEnableAnimations(options?.areAnimationsEnabled === true);\n const baseElement: Container = options?.baseElement ?? TOPLEVELS;\n const Wrapper = options?.wrapper;\n const resolved = resolveContainer(options?.container);\n\n const root = createReconcilerRoot({\n containerInfo: resolved.containerInfo,\n ...renderErrorHandlers(options),\n });\n\n const active: ActiveRender = { root, window: resolved.window };\n activeRenders.add(active);\n addToCleanupQueue(disposeAllActiveRenders);\n addToCleanupQueue(clearScreen);\n addToCleanupQueue(resetClipboard);\n\n const wrap = (node: ReactNode): ReactNode => {\n const wrapped = Wrapper ? <Wrapper>{node}</Wrapper> : node;\n\n return options?.isReactStrictMode ? <StrictMode>{wrapped}</StrictMode> : wrapped;\n };\n\n await update(wrap(element), root);\n presentHarnessWindow(resolved.window);\n await settleRender(resolved, options?.container, \"render\");\n const container = resolveResultContainer(resolved, options?.container, baseElement);\n\n const result: RenderResult<Q> = {\n ...within(baseElement, options?.queries),\n container,\n baseElement,\n unmount: async () => {\n await disposeActiveRender(active);\n },\n rerender: async (newElement: ReactNode) => {\n await update(wrap(newElement), root);\n await settleRender(resolved, options?.container, \"rerender\");\n },\n debug: (element: Container | Container[] = baseElement, debugOptions?: PrettyWidgetOptions) => {\n logWidget(element, debugOptions);\n },\n logRoles: () => {\n logRoles(baseElement);\n },\n screenshot: (screenshotOptions?: ScreenshotOptions) => captureScreen(screenshotOptions),\n };\n\n setScreen(result);\n\n return result;\n};\n\n/**\n * Unmounts every active render and runs all registered cleanup callbacks,\n * resetting the screen and clipboard. Called automatically after each test.\n */\nconst cleanup = async (): Promise<void> => {\n await runCleanup();\n};\n\nexport { render, cleanup };\n"]}
|
package/dist/role-helpers.d.ts
CHANGED
|
@@ -9,15 +9,17 @@ import { type Container } from "./traversal.js";
|
|
|
9
9
|
declare const formatRole: (role: Gtk.AccessibleRole) => string;
|
|
10
10
|
declare const formatRoleList: (roles: Iterable<Gtk.AccessibleRole>) => string;
|
|
11
11
|
/**
|
|
12
|
-
* Groups every widget in a container's tree by its accessible role name.
|
|
12
|
+
* Groups every mapped widget in a container's tree by its accessible role name. Widgets that are not
|
|
13
|
+
* mapped are left out.
|
|
13
14
|
*
|
|
14
15
|
* @param container The scope to traverse.
|
|
15
|
-
* @returns A map from role name to the widgets that have that role.
|
|
16
|
+
* @returns A map from role name to the mapped widgets that have that role.
|
|
16
17
|
*/
|
|
17
18
|
declare const getRoles: (container: Container) => Map<string, Gtk.Widget[]>;
|
|
18
19
|
/**
|
|
19
20
|
* Formats the accessible roles in a container's tree as a readable string,
|
|
20
21
|
* listing each role together with its widgets and their accessible names.
|
|
22
|
+
* Widgets that are not mapped are left out.
|
|
21
23
|
*
|
|
22
24
|
* @param container The scope to inspect.
|
|
23
25
|
*/
|
|
@@ -29,5 +31,12 @@ declare const prettyRoles: (container: Container) => string;
|
|
|
29
31
|
* @param container The scope to inspect.
|
|
30
32
|
*/
|
|
31
33
|
declare const logRoles: (container: Container) => void;
|
|
32
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Returns the heading or hierarchy level GTK reports for a widget, or undefined when it declares
|
|
36
|
+
* none.
|
|
37
|
+
*
|
|
38
|
+
* @param widget The widget to read the level from.
|
|
39
|
+
*/
|
|
40
|
+
declare const computeHeadingLevel: (widget: Gtk.Widget) => number | undefined;
|
|
41
|
+
export { computeHeadingLevel, formatRole, formatRoleList, getRoles, prettyRoles, logRoles };
|
|
33
42
|
//# sourceMappingURL=role-helpers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"role-helpers.d.ts","sourceRoot":"","sources":["../src/role-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAEpC,OAAO,EAAE,KAAK,SAAS,EAAY,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"role-helpers.d.ts","sourceRoot":"","sources":["../src/role-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAEpC,OAAO,EAAE,KAAK,SAAS,EAAY,MAAM,gBAAgB,CAAC;AAc1D;;;;;GAKG;AACH,QAAA,MAAM,UAAU,GAAI,MAAM,GAAG,CAAC,cAAc,KAAG,MAQ9C,CAAC;AAEF,QAAA,MAAM,cAAc,GAAI,OAAO,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC,KAAG,MAe7D,CAAC;AAEF;;;;;;GAMG;AACH,QAAA,MAAM,QAAQ,GAAI,WAAW,SAAS,KAAG,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAehE,CAAC;AAUF;;;;;;GAMG;AACH,QAAA,MAAM,WAAW,GAAI,WAAW,SAAS,KAAG,MAqB3C,CAAC;AAEF;;;;;GAKG;AACH,QAAA,MAAM,QAAQ,GAAI,WAAW,SAAS,KAAG,IAExC,CAAC;AAEF;;;;;GAKG;AACH,QAAA,MAAM,mBAAmB,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,MAAM,GAAG,SAAgD,CAAC;AAE5G,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC"}
|
package/dist/role-helpers.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as Gtk from "@gtkx/gi/gtk";
|
|
2
2
|
import { sortStringsBy } from "@gtkx/utils";
|
|
3
3
|
import { traverse } from "./traversal.js";
|
|
4
|
-
import { getWidgetAccessibleName } from "./widget-accessible-properties.js";
|
|
4
|
+
import { getWidgetAccessibleName, getWidgetLevel } from "./widget-accessible-properties.js";
|
|
5
|
+
import { getTypeTag } from "./widget-getters.js";
|
|
5
6
|
const ROLE_NAMES_BY_VALUE = enumNamesByValue(Gtk.AccessibleRole);
|
|
6
7
|
function enumNamesByValue(enumObject) {
|
|
7
8
|
return new Map(Object.entries(enumObject)
|
|
@@ -34,10 +35,11 @@ const formatRoleList = (roles) => {
|
|
|
34
35
|
return `${head.join(", ")}, or ${last}`;
|
|
35
36
|
};
|
|
36
37
|
/**
|
|
37
|
-
* Groups every widget in a container's tree by its accessible role name.
|
|
38
|
+
* Groups every mapped widget in a container's tree by its accessible role name. Widgets that are not
|
|
39
|
+
* mapped are left out.
|
|
38
40
|
*
|
|
39
41
|
* @param container The scope to traverse.
|
|
40
|
-
* @returns A map from role name to the widgets that have that role.
|
|
42
|
+
* @returns A map from role name to the mapped widgets that have that role.
|
|
41
43
|
*/
|
|
42
44
|
const getRoles = (container) => {
|
|
43
45
|
const roles = new Map();
|
|
@@ -54,7 +56,7 @@ const getRoles = (container) => {
|
|
|
54
56
|
return roles;
|
|
55
57
|
};
|
|
56
58
|
const formatWidgetPreview = (widget, name) => {
|
|
57
|
-
const tagName = widget
|
|
59
|
+
const tagName = getTypeTag(widget);
|
|
58
60
|
const roleAttr = formatRole(widget.getAccessibleRole());
|
|
59
61
|
const nameDisplay = name ? `Name "${name}"` : 'Name ""';
|
|
60
62
|
return `${nameDisplay}: <${tagName} role="${roleAttr}">${name ?? ""}</${tagName}>`;
|
|
@@ -62,6 +64,7 @@ const formatWidgetPreview = (widget, name) => {
|
|
|
62
64
|
/**
|
|
63
65
|
* Formats the accessible roles in a container's tree as a readable string,
|
|
64
66
|
* listing each role together with its widgets and their accessible names.
|
|
67
|
+
* Widgets that are not mapped are left out.
|
|
65
68
|
*
|
|
66
69
|
* @param container The scope to inspect.
|
|
67
70
|
*/
|
|
@@ -90,5 +93,12 @@ const prettyRoles = (container) => {
|
|
|
90
93
|
const logRoles = (container) => {
|
|
91
94
|
console.log(prettyRoles(container));
|
|
92
95
|
};
|
|
93
|
-
|
|
96
|
+
/**
|
|
97
|
+
* Returns the heading or hierarchy level GTK reports for a widget, or undefined when it declares
|
|
98
|
+
* none.
|
|
99
|
+
*
|
|
100
|
+
* @param widget The widget to read the level from.
|
|
101
|
+
*/
|
|
102
|
+
const computeHeadingLevel = (widget) => getWidgetLevel(widget) ?? undefined;
|
|
103
|
+
export { computeHeadingLevel, formatRole, formatRoleList, getRoles, prettyRoles, logRoles };
|
|
94
104
|
//# sourceMappingURL=role-helpers.js.map
|
package/dist/role-helpers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"role-helpers.js","sourceRoot":"","sources":["../src/role-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAkB,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"role-helpers.js","sourceRoot":"","sources":["../src/role-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAkB,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAC5F,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,MAAM,mBAAmB,GAAG,gBAAgB,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;AAEjE,SAAS,gBAAgB,CAAC,UAA2C;IACjE,OAAO,IAAI,GAAG,CACV,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;SACrB,MAAM,CAAC,CAAC,KAAK,EAA6B,EAAE,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC;SAC1E,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAC7C,CAAC;AACN,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,GAAG,CAAC,IAAwB,EAAU,EAAE;IACpD,MAAM,IAAI,GAAG,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAE3C,IAAI,CAAC,IAAI,EAAE,CAAC;QACR,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAED,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;AAC9B,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,KAAmC,EAAU,EAAE;IACnE,MAAM,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IAEvE,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACpB,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1B,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAChC,MAAM,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAEhC,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;AAC5C,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,QAAQ,GAAG,CAAC,SAAoB,EAA6B,EAAE;IACjE,MAAM,KAAK,GAA8B,IAAI,GAAG,EAAE,CAAC;IAEnD,KAAK,MAAM,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACvC,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAErC,IAAI,QAAQ,EAAE,CAAC;YACX,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1B,CAAC;aAAM,CAAC;YACJ,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;QAClC,CAAC;IACL,CAAC;IAED,OAAO,KAAK,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,CAAC,MAAkB,EAAE,IAAmB,EAAU,EAAE;IAC5E,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC,CAAC;IACxD,MAAM,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,IAAI,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;IAExD,OAAO,GAAG,WAAW,MAAM,OAAO,UAAU,QAAQ,KAAK,IAAI,IAAI,EAAE,KAAK,OAAO,GAAG,CAAC;AACvF,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,WAAW,GAAG,CAAC,SAAoB,EAAU,EAAE;IACjD,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;IAElC,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACnB,OAAO,+CAA+C,CAAC;IAC3D,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,WAAW,GAAG,aAAa,CAAC,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC;IAExE,KAAK,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,WAAW,EAAE,CAAC;QAC5C,KAAK,CAAC,IAAI,CAAC,GAAG,QAAQ,GAAG,CAAC,CAAC;QAE3B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,KAAK,mBAAmB,CAAC,MAAM,EAAE,uBAAuB,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;QACpF,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnB,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;AACtC,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,QAAQ,GAAG,CAAC,SAAoB,EAAQ,EAAE;IAC5C,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC;AACxC,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,mBAAmB,GAAG,CAAC,MAAkB,EAAsB,EAAE,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC;AAE5G,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC","sourcesContent":["import * as Gtk from \"@gtkx/gi/gtk\";\nimport { sortStringsBy } from \"@gtkx/utils\";\nimport { type Container, traverse } from \"./traversal.js\";\nimport { getWidgetAccessibleName, getWidgetLevel } from \"./widget-accessible-properties.js\";\nimport { getTypeTag } from \"./widget-getters.js\";\n\nconst ROLE_NAMES_BY_VALUE = enumNamesByValue(Gtk.AccessibleRole);\n\nfunction enumNamesByValue(enumObject: Record<string, string | number>): Map<number, string> {\n return new Map<number, string>(\n Object.entries(enumObject)\n .filter((entry): entry is [string, number] => typeof entry[1] === \"number\")\n .map(([name, value]) => [value, name]),\n );\n}\n\n/**\n * Converts an accessible role enum value into its lowercase name, falling back\n * to the numeric value when the role is unknown.\n *\n * @param role The accessible role to format.\n */\nconst formatRole = (role: Gtk.AccessibleRole): string => {\n const name = ROLE_NAMES_BY_VALUE.get(role);\n\n if (!name) {\n return String(role);\n }\n\n return name.toLowerCase();\n};\n\nconst formatRoleList = (roles: Iterable<Gtk.AccessibleRole>): string => {\n const names = [...roles].map((role) => formatRole(role).toUpperCase());\n\n if (names.length <= 1) {\n return names.join(\"\");\n }\n\n if (names.length === 2) {\n return names.join(\" or \");\n }\n\n const head = names.slice(0, -1);\n const last = names.at(-1) ?? \"\";\n\n return `${head.join(\", \")}, or ${last}`;\n};\n\n/**\n * Groups every mapped widget in a container's tree by its accessible role name. Widgets that are not\n * mapped are left out.\n *\n * @param container The scope to traverse.\n * @returns A map from role name to the mapped widgets that have that role.\n */\nconst getRoles = (container: Container): Map<string, Gtk.Widget[]> => {\n const roles: Map<string, Gtk.Widget[]> = new Map();\n\n for (const widget of traverse(container)) {\n const roleName = formatRole(widget.getAccessibleRole());\n const existing = roles.get(roleName);\n\n if (existing) {\n existing.push(widget);\n } else {\n roles.set(roleName, [widget]);\n }\n }\n\n return roles;\n};\n\nconst formatWidgetPreview = (widget: Gtk.Widget, name: string | null): string => {\n const tagName = getTypeTag(widget);\n const roleAttr = formatRole(widget.getAccessibleRole());\n const nameDisplay = name ? `Name \"${name}\"` : 'Name \"\"';\n\n return `${nameDisplay}: <${tagName} role=\"${roleAttr}\">${name ?? \"\"}</${tagName}>`;\n};\n\n/**\n * Formats the accessible roles in a container's tree as a readable string,\n * listing each role together with its widgets and their accessible names.\n * Widgets that are not mapped are left out.\n *\n * @param container The scope to inspect.\n */\nconst prettyRoles = (container: Container): string => {\n const roles = getRoles(container);\n\n if (roles.size === 0) {\n return \"No accessible roles found in the widget tree.\";\n }\n\n const lines: string[] = [];\n const sortedRoles = sortStringsBy([...roles], ([roleName]) => roleName);\n\n for (const [roleName, widgets] of sortedRoles) {\n lines.push(`${roleName}:`);\n\n for (const widget of widgets) {\n lines.push(` ${formatWidgetPreview(widget, getWidgetAccessibleName(widget))}`);\n }\n\n lines.push(\"\");\n }\n\n return lines.join(\"\\n\").trimEnd();\n};\n\n/**\n * Prints the accessible roles in a container's tree to the console using\n * {@link prettyRoles}.\n *\n * @param container The scope to inspect.\n */\nconst logRoles = (container: Container): void => {\n console.log(prettyRoles(container));\n};\n\n/**\n * Returns the heading or hierarchy level GTK reports for a widget, or undefined when it declares\n * none.\n *\n * @param widget The widget to read the level from.\n */\nconst computeHeadingLevel = (widget: Gtk.Widget): number | undefined => getWidgetLevel(widget) ?? undefined;\n\nexport { computeHeadingLevel, formatRole, formatRoleList, getRoles, prettyRoles, logRoles };\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
2
|
+
declare const isNameProhibited: (role: Gtk.AccessibleRole) => boolean;
|
|
3
|
+
declare const isNameFromAuthor: (role: Gtk.AccessibleRole) => boolean;
|
|
4
|
+
export { isNameFromAuthor, isNameProhibited };
|
|
5
|
+
//# sourceMappingURL=role-naming.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"role-naming.d.ts","sourceRoot":"","sources":["../src/role-naming.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AA+FpC,QAAA,MAAM,gBAAgB,GAAI,MAAM,GAAG,CAAC,cAAc,KAAG,OAA+C,CAAC;AACrG,QAAA,MAAM,gBAAgB,GAAI,MAAM,GAAG,CAAC,cAAc,KAAG,OAAgD,CAAC;AAEtG,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
2
|
+
const FROM_AUTHOR = 1;
|
|
3
|
+
const FROM_CONTENT = 2;
|
|
4
|
+
const PROHIBITED = 4;
|
|
5
|
+
const NAMING = {
|
|
6
|
+
[Gtk.AccessibleRole.ALERT]: FROM_AUTHOR,
|
|
7
|
+
[Gtk.AccessibleRole.ALERT_DIALOG]: FROM_AUTHOR,
|
|
8
|
+
[Gtk.AccessibleRole.APPLICATION]: FROM_AUTHOR,
|
|
9
|
+
[Gtk.AccessibleRole.ARTICLE]: FROM_AUTHOR,
|
|
10
|
+
[Gtk.AccessibleRole.BANNER]: FROM_AUTHOR,
|
|
11
|
+
[Gtk.AccessibleRole.BLOCK_QUOTE]: FROM_AUTHOR,
|
|
12
|
+
[Gtk.AccessibleRole.BUTTON]: FROM_AUTHOR | FROM_CONTENT,
|
|
13
|
+
[Gtk.AccessibleRole.CAPTION]: PROHIBITED,
|
|
14
|
+
[Gtk.AccessibleRole.CELL]: FROM_AUTHOR | FROM_CONTENT,
|
|
15
|
+
[Gtk.AccessibleRole.CHECKBOX]: FROM_AUTHOR | FROM_CONTENT,
|
|
16
|
+
[Gtk.AccessibleRole.COLUMN_HEADER]: FROM_AUTHOR | FROM_CONTENT,
|
|
17
|
+
[Gtk.AccessibleRole.COMBO_BOX]: FROM_AUTHOR,
|
|
18
|
+
[Gtk.AccessibleRole.COMMAND]: PROHIBITED,
|
|
19
|
+
[Gtk.AccessibleRole.COMMENT]: FROM_AUTHOR | FROM_CONTENT,
|
|
20
|
+
[Gtk.AccessibleRole.COMPOSITE]: PROHIBITED,
|
|
21
|
+
[Gtk.AccessibleRole.DIALOG]: FROM_AUTHOR,
|
|
22
|
+
[Gtk.AccessibleRole.DOCUMENT]: FROM_AUTHOR,
|
|
23
|
+
[Gtk.AccessibleRole.FEED]: FROM_AUTHOR,
|
|
24
|
+
[Gtk.AccessibleRole.FORM]: FROM_AUTHOR,
|
|
25
|
+
[Gtk.AccessibleRole.GENERIC]: PROHIBITED,
|
|
26
|
+
[Gtk.AccessibleRole.GRID]: FROM_AUTHOR,
|
|
27
|
+
[Gtk.AccessibleRole.GRID_CELL]: FROM_AUTHOR | FROM_CONTENT,
|
|
28
|
+
[Gtk.AccessibleRole.GROUP]: FROM_AUTHOR,
|
|
29
|
+
[Gtk.AccessibleRole.HEADING]: FROM_AUTHOR | FROM_CONTENT,
|
|
30
|
+
[Gtk.AccessibleRole.IMG]: FROM_AUTHOR,
|
|
31
|
+
[Gtk.AccessibleRole.INPUT]: PROHIBITED,
|
|
32
|
+
[Gtk.AccessibleRole.LABEL]: FROM_AUTHOR | FROM_CONTENT,
|
|
33
|
+
[Gtk.AccessibleRole.LANDMARK]: PROHIBITED,
|
|
34
|
+
[Gtk.AccessibleRole.LEGEND]: PROHIBITED,
|
|
35
|
+
[Gtk.AccessibleRole.LINK]: FROM_AUTHOR | FROM_CONTENT,
|
|
36
|
+
[Gtk.AccessibleRole.LIST]: FROM_AUTHOR,
|
|
37
|
+
[Gtk.AccessibleRole.LIST_BOX]: FROM_AUTHOR,
|
|
38
|
+
[Gtk.AccessibleRole.LIST_ITEM]: FROM_AUTHOR,
|
|
39
|
+
[Gtk.AccessibleRole.LOG]: FROM_AUTHOR,
|
|
40
|
+
[Gtk.AccessibleRole.MAIN]: FROM_AUTHOR,
|
|
41
|
+
[Gtk.AccessibleRole.MARQUEE]: FROM_AUTHOR,
|
|
42
|
+
[Gtk.AccessibleRole.MATH]: FROM_AUTHOR,
|
|
43
|
+
[Gtk.AccessibleRole.METER]: FROM_AUTHOR,
|
|
44
|
+
[Gtk.AccessibleRole.MENU]: FROM_AUTHOR,
|
|
45
|
+
[Gtk.AccessibleRole.MENU_BAR]: FROM_AUTHOR,
|
|
46
|
+
[Gtk.AccessibleRole.MENU_ITEM]: FROM_AUTHOR | FROM_CONTENT,
|
|
47
|
+
[Gtk.AccessibleRole.MENU_ITEM_CHECKBOX]: FROM_AUTHOR | FROM_CONTENT,
|
|
48
|
+
[Gtk.AccessibleRole.MENU_ITEM_RADIO]: FROM_AUTHOR | FROM_CONTENT,
|
|
49
|
+
[Gtk.AccessibleRole.NAVIGATION]: FROM_AUTHOR,
|
|
50
|
+
[Gtk.AccessibleRole.NONE]: PROHIBITED,
|
|
51
|
+
[Gtk.AccessibleRole.NOTE]: FROM_AUTHOR,
|
|
52
|
+
[Gtk.AccessibleRole.OPTION]: FROM_AUTHOR | FROM_CONTENT,
|
|
53
|
+
[Gtk.AccessibleRole.PARAGRAPH]: PROHIBITED,
|
|
54
|
+
[Gtk.AccessibleRole.PRESENTATION]: PROHIBITED,
|
|
55
|
+
[Gtk.AccessibleRole.PROGRESS_BAR]: FROM_AUTHOR,
|
|
56
|
+
[Gtk.AccessibleRole.RADIO]: FROM_AUTHOR | FROM_CONTENT,
|
|
57
|
+
[Gtk.AccessibleRole.RADIO_GROUP]: FROM_AUTHOR,
|
|
58
|
+
[Gtk.AccessibleRole.RANGE]: PROHIBITED,
|
|
59
|
+
[Gtk.AccessibleRole.REGION]: FROM_AUTHOR,
|
|
60
|
+
[Gtk.AccessibleRole.ROW]: FROM_AUTHOR | FROM_CONTENT,
|
|
61
|
+
[Gtk.AccessibleRole.ROW_GROUP]: FROM_AUTHOR,
|
|
62
|
+
[Gtk.AccessibleRole.ROW_HEADER]: FROM_AUTHOR | FROM_CONTENT,
|
|
63
|
+
[Gtk.AccessibleRole.SCROLLBAR]: FROM_AUTHOR,
|
|
64
|
+
[Gtk.AccessibleRole.SEARCH]: FROM_AUTHOR,
|
|
65
|
+
[Gtk.AccessibleRole.SEARCH_BOX]: FROM_AUTHOR,
|
|
66
|
+
[Gtk.AccessibleRole.SECTION]: PROHIBITED,
|
|
67
|
+
[Gtk.AccessibleRole.SECTION_HEAD]: PROHIBITED,
|
|
68
|
+
[Gtk.AccessibleRole.SELECT]: PROHIBITED,
|
|
69
|
+
[Gtk.AccessibleRole.SEPARATOR]: FROM_AUTHOR,
|
|
70
|
+
[Gtk.AccessibleRole.SLIDER]: FROM_AUTHOR,
|
|
71
|
+
[Gtk.AccessibleRole.SPIN_BUTTON]: FROM_AUTHOR,
|
|
72
|
+
[Gtk.AccessibleRole.STATUS]: FROM_AUTHOR,
|
|
73
|
+
[Gtk.AccessibleRole.STRUCTURE]: PROHIBITED,
|
|
74
|
+
[Gtk.AccessibleRole.SWITCH]: FROM_AUTHOR | FROM_CONTENT,
|
|
75
|
+
[Gtk.AccessibleRole.TAB]: FROM_AUTHOR | FROM_CONTENT,
|
|
76
|
+
[Gtk.AccessibleRole.TABLE]: FROM_AUTHOR,
|
|
77
|
+
[Gtk.AccessibleRole.TAB_LIST]: FROM_AUTHOR,
|
|
78
|
+
[Gtk.AccessibleRole.TAB_PANEL]: FROM_AUTHOR,
|
|
79
|
+
[Gtk.AccessibleRole.TERMINAL]: FROM_AUTHOR,
|
|
80
|
+
[Gtk.AccessibleRole.TEXT_BOX]: FROM_AUTHOR,
|
|
81
|
+
[Gtk.AccessibleRole.TIME]: FROM_AUTHOR,
|
|
82
|
+
[Gtk.AccessibleRole.TIMER]: FROM_AUTHOR,
|
|
83
|
+
[Gtk.AccessibleRole.TOGGLE_BUTTON]: FROM_AUTHOR,
|
|
84
|
+
[Gtk.AccessibleRole.TOOLBAR]: FROM_AUTHOR,
|
|
85
|
+
[Gtk.AccessibleRole.TOOLTIP]: FROM_AUTHOR | FROM_CONTENT,
|
|
86
|
+
[Gtk.AccessibleRole.TREE]: FROM_AUTHOR,
|
|
87
|
+
[Gtk.AccessibleRole.TREE_GRID]: FROM_AUTHOR,
|
|
88
|
+
[Gtk.AccessibleRole.TREE_ITEM]: FROM_AUTHOR | FROM_CONTENT,
|
|
89
|
+
[Gtk.AccessibleRole.WIDGET]: FROM_AUTHOR | FROM_CONTENT,
|
|
90
|
+
[Gtk.AccessibleRole.WINDOW]: FROM_AUTHOR,
|
|
91
|
+
};
|
|
92
|
+
const namingFor = (role) => NAMING[role] ?? 0;
|
|
93
|
+
const isNameProhibited = (role) => (namingFor(role) & PROHIBITED) !== 0;
|
|
94
|
+
const isNameFromAuthor = (role) => (namingFor(role) & FROM_AUTHOR) !== 0;
|
|
95
|
+
export { isNameFromAuthor, isNameProhibited };
|
|
96
|
+
//# sourceMappingURL=role-naming.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"role-naming.js","sourceRoot":"","sources":["../src/role-naming.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Gtk from \"@gtkx/gi/gtk\";\n\nconst FROM_AUTHOR = 1;\nconst FROM_CONTENT = 2;\nconst PROHIBITED = 4;\n\nconst NAMING: Partial<Record<Gtk.AccessibleRole, number>> = {\n [Gtk.AccessibleRole.ALERT]: FROM_AUTHOR,\n [Gtk.AccessibleRole.ALERT_DIALOG]: FROM_AUTHOR,\n [Gtk.AccessibleRole.APPLICATION]: FROM_AUTHOR,\n [Gtk.AccessibleRole.ARTICLE]: FROM_AUTHOR,\n [Gtk.AccessibleRole.BANNER]: FROM_AUTHOR,\n [Gtk.AccessibleRole.BLOCK_QUOTE]: FROM_AUTHOR,\n [Gtk.AccessibleRole.BUTTON]: FROM_AUTHOR | FROM_CONTENT,\n [Gtk.AccessibleRole.CAPTION]: PROHIBITED,\n [Gtk.AccessibleRole.CELL]: FROM_AUTHOR | FROM_CONTENT,\n [Gtk.AccessibleRole.CHECKBOX]: FROM_AUTHOR | FROM_CONTENT,\n [Gtk.AccessibleRole.COLUMN_HEADER]: FROM_AUTHOR | FROM_CONTENT,\n [Gtk.AccessibleRole.COMBO_BOX]: FROM_AUTHOR,\n [Gtk.AccessibleRole.COMMAND]: PROHIBITED,\n [Gtk.AccessibleRole.COMMENT]: FROM_AUTHOR | FROM_CONTENT,\n [Gtk.AccessibleRole.COMPOSITE]: PROHIBITED,\n [Gtk.AccessibleRole.DIALOG]: FROM_AUTHOR,\n [Gtk.AccessibleRole.DOCUMENT]: FROM_AUTHOR,\n [Gtk.AccessibleRole.FEED]: FROM_AUTHOR,\n [Gtk.AccessibleRole.FORM]: FROM_AUTHOR,\n [Gtk.AccessibleRole.GENERIC]: PROHIBITED,\n [Gtk.AccessibleRole.GRID]: FROM_AUTHOR,\n [Gtk.AccessibleRole.GRID_CELL]: FROM_AUTHOR | FROM_CONTENT,\n [Gtk.AccessibleRole.GROUP]: FROM_AUTHOR,\n [Gtk.AccessibleRole.HEADING]: FROM_AUTHOR | FROM_CONTENT,\n [Gtk.AccessibleRole.IMG]: FROM_AUTHOR,\n [Gtk.AccessibleRole.INPUT]: PROHIBITED,\n [Gtk.AccessibleRole.LABEL]: FROM_AUTHOR | FROM_CONTENT,\n [Gtk.AccessibleRole.LANDMARK]: PROHIBITED,\n [Gtk.AccessibleRole.LEGEND]: PROHIBITED,\n [Gtk.AccessibleRole.LINK]: FROM_AUTHOR | FROM_CONTENT,\n [Gtk.AccessibleRole.LIST]: FROM_AUTHOR,\n [Gtk.AccessibleRole.LIST_BOX]: FROM_AUTHOR,\n [Gtk.AccessibleRole.LIST_ITEM]: FROM_AUTHOR,\n [Gtk.AccessibleRole.LOG]: FROM_AUTHOR,\n [Gtk.AccessibleRole.MAIN]: FROM_AUTHOR,\n [Gtk.AccessibleRole.MARQUEE]: FROM_AUTHOR,\n [Gtk.AccessibleRole.MATH]: FROM_AUTHOR,\n [Gtk.AccessibleRole.METER]: FROM_AUTHOR,\n [Gtk.AccessibleRole.MENU]: FROM_AUTHOR,\n [Gtk.AccessibleRole.MENU_BAR]: FROM_AUTHOR,\n [Gtk.AccessibleRole.MENU_ITEM]: FROM_AUTHOR | FROM_CONTENT,\n [Gtk.AccessibleRole.MENU_ITEM_CHECKBOX]: FROM_AUTHOR | FROM_CONTENT,\n [Gtk.AccessibleRole.MENU_ITEM_RADIO]: FROM_AUTHOR | FROM_CONTENT,\n [Gtk.AccessibleRole.NAVIGATION]: FROM_AUTHOR,\n [Gtk.AccessibleRole.NONE]: PROHIBITED,\n [Gtk.AccessibleRole.NOTE]: FROM_AUTHOR,\n [Gtk.AccessibleRole.OPTION]: FROM_AUTHOR | FROM_CONTENT,\n [Gtk.AccessibleRole.PARAGRAPH]: PROHIBITED,\n [Gtk.AccessibleRole.PRESENTATION]: PROHIBITED,\n [Gtk.AccessibleRole.PROGRESS_BAR]: FROM_AUTHOR,\n [Gtk.AccessibleRole.RADIO]: FROM_AUTHOR | FROM_CONTENT,\n [Gtk.AccessibleRole.RADIO_GROUP]: FROM_AUTHOR,\n [Gtk.AccessibleRole.RANGE]: PROHIBITED,\n [Gtk.AccessibleRole.REGION]: FROM_AUTHOR,\n [Gtk.AccessibleRole.ROW]: FROM_AUTHOR | FROM_CONTENT,\n [Gtk.AccessibleRole.ROW_GROUP]: FROM_AUTHOR,\n [Gtk.AccessibleRole.ROW_HEADER]: FROM_AUTHOR | FROM_CONTENT,\n [Gtk.AccessibleRole.SCROLLBAR]: FROM_AUTHOR,\n [Gtk.AccessibleRole.SEARCH]: FROM_AUTHOR,\n [Gtk.AccessibleRole.SEARCH_BOX]: FROM_AUTHOR,\n [Gtk.AccessibleRole.SECTION]: PROHIBITED,\n [Gtk.AccessibleRole.SECTION_HEAD]: PROHIBITED,\n [Gtk.AccessibleRole.SELECT]: PROHIBITED,\n [Gtk.AccessibleRole.SEPARATOR]: FROM_AUTHOR,\n [Gtk.AccessibleRole.SLIDER]: FROM_AUTHOR,\n [Gtk.AccessibleRole.SPIN_BUTTON]: FROM_AUTHOR,\n [Gtk.AccessibleRole.STATUS]: FROM_AUTHOR,\n [Gtk.AccessibleRole.STRUCTURE]: PROHIBITED,\n [Gtk.AccessibleRole.SWITCH]: FROM_AUTHOR | FROM_CONTENT,\n [Gtk.AccessibleRole.TAB]: FROM_AUTHOR | FROM_CONTENT,\n [Gtk.AccessibleRole.TABLE]: FROM_AUTHOR,\n [Gtk.AccessibleRole.TAB_LIST]: FROM_AUTHOR,\n [Gtk.AccessibleRole.TAB_PANEL]: FROM_AUTHOR,\n [Gtk.AccessibleRole.TERMINAL]: FROM_AUTHOR,\n [Gtk.AccessibleRole.TEXT_BOX]: FROM_AUTHOR,\n [Gtk.AccessibleRole.TIME]: FROM_AUTHOR,\n [Gtk.AccessibleRole.TIMER]: FROM_AUTHOR,\n [Gtk.AccessibleRole.TOGGLE_BUTTON]: FROM_AUTHOR,\n [Gtk.AccessibleRole.TOOLBAR]: FROM_AUTHOR,\n [Gtk.AccessibleRole.TOOLTIP]: FROM_AUTHOR | FROM_CONTENT,\n [Gtk.AccessibleRole.TREE]: FROM_AUTHOR,\n [Gtk.AccessibleRole.TREE_GRID]: FROM_AUTHOR,\n [Gtk.AccessibleRole.TREE_ITEM]: FROM_AUTHOR | FROM_CONTENT,\n [Gtk.AccessibleRole.WIDGET]: FROM_AUTHOR | FROM_CONTENT,\n [Gtk.AccessibleRole.WINDOW]: FROM_AUTHOR,\n};\n\nconst namingFor = (role: Gtk.AccessibleRole): number => NAMING[role] ?? 0;\nconst isNameProhibited = (role: Gtk.AccessibleRole): boolean => (namingFor(role) & PROHIBITED) !== 0;\nconst isNameFromAuthor = (role: Gtk.AccessibleRole): boolean => (namingFor(role) & FROM_AUTHOR) !== 0;\n\nexport { isNameFromAuthor, isNameProhibited };\n"]}
|