@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 @@
|
|
|
1
|
+
{"version":3,"file":"widget-getters.d.ts","sourceRoot":"","sources":["../src/widget-getters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,OAAO,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,KAAK,GAAG,MAAM,cAAc,CAAC;AAQzC,QAAA,MAAM,iBAAiB,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,MAAM,GAAG,IAAyC,CAAC;AA2BnG,QAAA,MAAM,UAAU,GAAI,QAAQ,OAAO,CAAC,MAAM,KAAG,MAU5C,CAAC;AAEF,QAAA,MAAM,mBAAmB,GAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,MAAM,MAAM,KAAG,OACL,CAAC;AAE5D,QAAA,MAAM,eAAe,GAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,MAAM,MAAM,KAAG,OACL,CAAC;AAGxD,QAAA,MAAM,iBAAiB,GAAI,IAAI,SAAS,OAAO,EAAE,EAAE,MAAM,EACrD,QAAQ,GAAG,CAAC,MAAM,EAClB,MAAM,MAAM,KACb,CAAC,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC,GAAG,IAIhC,CAAC;AAEF,QAAA,MAAM,iBAAiB,GAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,QAAQ,MAAM,KAAG,OAAO,GAAG,IAIzE,CAAC;AAEF,QAAA,MAAM,gBAAgB,GAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,QAAQ,MAAM,KAAG,MAAM,GAAG,IAIvE,CAAC;AAEF,OAAO,EACH,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,EACV,iBAAiB,EACjB,eAAe,EACf,mBAAmB,GACtB,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { getClassType, getInstanceType, TYPE_INVALID, typeName } from "@gtkx/runtime";
|
|
2
|
+
import { resolveWrapperClass } from "@gtkx/runtime/internal";
|
|
3
|
+
import { walkClassChain } from "@gtkx/utils";
|
|
4
|
+
const UNNAMED_TYPE_TAG = "Object";
|
|
5
|
+
const getWidgetMethod = (widget, name) => Reflect.get(widget, name);
|
|
6
|
+
const getWidgetTypeName = (widget) => typeName(getInstanceType(widget));
|
|
7
|
+
const isClass = (value) => typeof value === "function";
|
|
8
|
+
const nonEmpty = (value) => typeof value === "string" && value.length > 0 ? value : undefined;
|
|
9
|
+
const getObjectClass = (object) => {
|
|
10
|
+
const cls = object.constructor;
|
|
11
|
+
return isClass(cls) ? cls : null;
|
|
12
|
+
};
|
|
13
|
+
const getNearestClassName = (object) => walkClassChain(getObjectClass(object), (ancestor) => nonEmpty(ancestor.name));
|
|
14
|
+
const getUntypedClassName = (object) => {
|
|
15
|
+
const cls = getObjectClass(object);
|
|
16
|
+
return cls !== null && getClassType(cls) === TYPE_INVALID ? nonEmpty(cls.name) : undefined;
|
|
17
|
+
};
|
|
18
|
+
const getExactWrapperName = (type) => {
|
|
19
|
+
const wrapper = resolveWrapperClass(type);
|
|
20
|
+
return wrapper !== null && getClassType(wrapper) === type ? nonEmpty(wrapper.name) : undefined;
|
|
21
|
+
};
|
|
22
|
+
const getTypeTag = (object) => {
|
|
23
|
+
const type = getInstanceType(object);
|
|
24
|
+
return (getUntypedClassName(object) ??
|
|
25
|
+
getExactWrapperName(type) ??
|
|
26
|
+
nonEmpty(typeName(type)) ??
|
|
27
|
+
getNearestClassName(object) ??
|
|
28
|
+
UNNAMED_TYPE_TAG);
|
|
29
|
+
};
|
|
30
|
+
const isDefaultWidgetName = (widget, name) => name.length === 0 || name === getWidgetTypeName(widget);
|
|
31
|
+
const hasWidgetMethod = (widget, name) => typeof getWidgetMethod(widget, name) === "function";
|
|
32
|
+
/* eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters -- callers name the signature */
|
|
33
|
+
const getCallableMethod = (widget, name) => {
|
|
34
|
+
const fn = getWidgetMethod(widget, name);
|
|
35
|
+
return typeof fn === "function" ? fn.bind(widget) : null;
|
|
36
|
+
};
|
|
37
|
+
const callBooleanGetter = (widget, method) => {
|
|
38
|
+
const value = getCallableMethod(widget, method)?.();
|
|
39
|
+
return typeof value === "boolean" ? value : null;
|
|
40
|
+
};
|
|
41
|
+
const callStringGetter = (widget, method) => {
|
|
42
|
+
const value = getCallableMethod(widget, method)?.();
|
|
43
|
+
return typeof value === "string" ? value : null;
|
|
44
|
+
};
|
|
45
|
+
export { callBooleanGetter, callStringGetter, getCallableMethod, getTypeTag, getWidgetTypeName, hasWidgetMethod, isDefaultWidgetName, };
|
|
46
|
+
//# sourceMappingURL=widget-getters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"widget-getters.js","sourceRoot":"","sources":["../src/widget-getters.ts"],"names":[],"mappings":"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","sourcesContent":["import type * as GObject from \"@gtkx/gi/gobject\";\nimport type * as Gtk from \"@gtkx/gi/gtk\";\nimport { getClassType, getInstanceType, TYPE_INVALID, typeName } from \"@gtkx/runtime\";\nimport { resolveWrapperClass } from \"@gtkx/runtime/internal\";\nimport { type AnyClass, walkClassChain } from \"@gtkx/utils\";\n\nconst UNNAMED_TYPE_TAG = \"Object\";\n\nconst getWidgetMethod = (widget: Gtk.Widget, name: string): unknown => Reflect.get(widget, name);\nconst getWidgetTypeName = (widget: Gtk.Widget): string | null => typeName(getInstanceType(widget));\nconst isClass = (value: unknown): value is AnyClass => typeof value === \"function\";\n\nconst nonEmpty = (value: unknown): string | undefined =>\n typeof value === \"string\" && value.length > 0 ? value : undefined;\n\nconst getObjectClass = (object: GObject.Object): AnyClass | null => {\n const cls: unknown = object.constructor;\n\n return isClass(cls) ? cls : null;\n};\n\nconst getNearestClassName = (object: GObject.Object): string | undefined =>\n walkClassChain(getObjectClass(object), (ancestor) => nonEmpty(ancestor.name));\n\nconst getUntypedClassName = (object: GObject.Object): string | undefined => {\n const cls = getObjectClass(object);\n\n return cls !== null && getClassType(cls) === TYPE_INVALID ? nonEmpty(cls.name) : undefined;\n};\n\nconst getExactWrapperName = (type: bigint): string | undefined => {\n const wrapper = resolveWrapperClass(type);\n\n return wrapper !== null && getClassType(wrapper) === type ? nonEmpty(wrapper.name) : undefined;\n};\n\nconst getTypeTag = (object: GObject.Object): string => {\n const type = getInstanceType(object);\n\n return (\n getUntypedClassName(object) ??\n getExactWrapperName(type) ??\n nonEmpty(typeName(type)) ??\n getNearestClassName(object) ??\n UNNAMED_TYPE_TAG\n );\n};\n\nconst isDefaultWidgetName = (widget: Gtk.Widget, name: string): boolean =>\n name.length === 0 || name === getWidgetTypeName(widget);\n\nconst hasWidgetMethod = (widget: Gtk.Widget, name: string): boolean =>\n typeof getWidgetMethod(widget, name) === \"function\";\n\n/* eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters -- callers name the signature */\nconst getCallableMethod = <Args extends unknown[], Result>(\n widget: Gtk.Widget,\n name: string,\n): ((...args: Args) => Result) | null => {\n const fn = getWidgetMethod(widget, name);\n\n return typeof fn === \"function\" ? (fn as (...args: Args) => Result).bind(widget) : null;\n};\n\nconst callBooleanGetter = (widget: Gtk.Widget, method: string): boolean | null => {\n const value = getCallableMethod<[], unknown>(widget, method)?.();\n\n return typeof value === \"boolean\" ? value : null;\n};\n\nconst callStringGetter = (widget: Gtk.Widget, method: string): string | null => {\n const value = getCallableMethod<[], unknown>(widget, method)?.();\n\n return typeof value === \"string\" ? value : null;\n};\n\nexport {\n callBooleanGetter,\n callStringGetter,\n getCallableMethod,\n getTypeTag,\n getWidgetTypeName,\n hasWidgetMethod,\n isDefaultWidgetName,\n};\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
2
|
+
declare const mappedToplevels: () => Gtk.Window[];
|
|
3
|
+
declare const isWindowAllocated: (window: Gtk.Window) => boolean;
|
|
4
|
+
declare const activeToplevel: () => Gtk.Window | null;
|
|
5
|
+
declare const isWindowActivated: (window: Gtk.Window) => boolean;
|
|
6
|
+
declare const isWindowBlockedByModal: (window: Gtk.Window) => boolean;
|
|
7
|
+
declare const findPresentedWindowFailure: (window: Gtk.Window) => string | null;
|
|
8
|
+
declare const findRenderedWindowFailure: (window: Gtk.Window) => string | null;
|
|
9
|
+
export { activeToplevel, findPresentedWindowFailure, findRenderedWindowFailure, isWindowActivated, isWindowAllocated, isWindowBlockedByModal, mappedToplevels, };
|
|
10
|
+
//# sourceMappingURL=window-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"window-state.d.ts","sourceRoot":"","sources":["../src/window-state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AASpC,QAAA,MAAM,eAAe,QAAO,GAAG,CAAC,MAAM,EACoE,CAAC;AAE3G,QAAA,MAAM,iBAAiB,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,OAI/C,CAAC;AAEF,QAAA,MAAM,cAAc,QAAO,GAAG,CAAC,MAAM,GAAG,IAAyE,CAAC;AAElH,QAAA,MAAM,iBAAiB,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,OACa,CAAC;AAqB9D,QAAA,MAAM,sBAAsB,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,OAC0B,CAAC;AAEhF,QAAA,MAAM,0BAA0B,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,MAAM,GAAG,IAMjE,CAAC;AAEF,QAAA,MAAM,yBAAyB,GAAI,QAAQ,GAAG,CAAC,MAAM,KAAG,MAAM,GAAG,IAMhE,CAAC;AAEF,OAAO,EACH,cAAc,EACd,0BAA0B,EAC1B,yBAAyB,EACzB,iBAAiB,EACjB,iBAAiB,EACjB,sBAAsB,EACtB,eAAe,GAClB,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
2
|
+
const WINDOW_NOT_ALLOCATED = "it was never allocated a size";
|
|
3
|
+
const WINDOW_NOT_ACTIVATED = "it never became active";
|
|
4
|
+
const NO_WINDOW_ACTIVATED = "no window of the application ever became active";
|
|
5
|
+
const canDisplayDeliverActivation = (window) => window.getDisplay().getDefaultSeat() !== null;
|
|
6
|
+
const isWindow = (widget) => widget instanceof Gtk.Window;
|
|
7
|
+
const mappedToplevels = () => Gtk.Window.listToplevels().filter((widget) => isWindow(widget)).filter((window) => window.getMapped());
|
|
8
|
+
const isWindowAllocated = (window) => {
|
|
9
|
+
const [isComputed, allocation] = window.computeBounds(window);
|
|
10
|
+
return isComputed && allocation.getWidth() > 0;
|
|
11
|
+
};
|
|
12
|
+
const activeToplevel = () => mappedToplevels().find((toplevel) => toplevel.isActive()) ?? null;
|
|
13
|
+
const isWindowActivated = (window) => !canDisplayDeliverActivation(window) || window.isActive();
|
|
14
|
+
const isApplicationActivated = (window) => !canDisplayDeliverActivation(window) || activeToplevel() !== null;
|
|
15
|
+
const isTransientDescendant = (window, ancestor) => {
|
|
16
|
+
for (let parent = window.getTransientFor(); parent !== null; parent = parent.getTransientFor()) {
|
|
17
|
+
if (parent === ancestor) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return false;
|
|
22
|
+
};
|
|
23
|
+
const isModalGrabHeldOver = (modal, window) => modal.getModal() &&
|
|
24
|
+
modal !== window &&
|
|
25
|
+
modal.getGroup() === window.getGroup() &&
|
|
26
|
+
!isTransientDescendant(window, modal);
|
|
27
|
+
const isWindowBlockedByModal = (window) => mappedToplevels().some((toplevel) => isModalGrabHeldOver(toplevel, window));
|
|
28
|
+
const findPresentedWindowFailure = (window) => {
|
|
29
|
+
if (!isWindowAllocated(window)) {
|
|
30
|
+
return WINDOW_NOT_ALLOCATED;
|
|
31
|
+
}
|
|
32
|
+
return isWindowActivated(window) ? null : WINDOW_NOT_ACTIVATED;
|
|
33
|
+
};
|
|
34
|
+
const findRenderedWindowFailure = (window) => {
|
|
35
|
+
if (!isWindowAllocated(window)) {
|
|
36
|
+
return WINDOW_NOT_ALLOCATED;
|
|
37
|
+
}
|
|
38
|
+
return isApplicationActivated(window) ? null : NO_WINDOW_ACTIVATED;
|
|
39
|
+
};
|
|
40
|
+
export { activeToplevel, findPresentedWindowFailure, findRenderedWindowFailure, isWindowActivated, isWindowAllocated, isWindowBlockedByModal, mappedToplevels, };
|
|
41
|
+
//# sourceMappingURL=window-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"window-state.js","sourceRoot":"","sources":["../src/window-state.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Gtk from \"@gtkx/gi/gtk\";\n\nconst WINDOW_NOT_ALLOCATED = \"it was never allocated a size\";\nconst WINDOW_NOT_ACTIVATED = \"it never became active\";\nconst NO_WINDOW_ACTIVATED = \"no window of the application ever became active\";\n\nconst canDisplayDeliverActivation = (window: Gtk.Window): boolean => window.getDisplay().getDefaultSeat() !== null;\nconst isWindow = (widget: Gtk.Widget): widget is Gtk.Window => widget instanceof Gtk.Window;\n\nconst mappedToplevels = (): Gtk.Window[] =>\n Gtk.Window.listToplevels().filter((widget) => isWindow(widget)).filter((window) => window.getMapped());\n\nconst isWindowAllocated = (window: Gtk.Window): boolean => {\n const [isComputed, allocation] = window.computeBounds(window);\n\n return isComputed && allocation.getWidth() > 0;\n};\n\nconst activeToplevel = (): Gtk.Window | null => mappedToplevels().find((toplevel) => toplevel.isActive()) ?? null;\n\nconst isWindowActivated = (window: Gtk.Window): boolean =>\n !canDisplayDeliverActivation(window) || window.isActive();\n\nconst isApplicationActivated = (window: Gtk.Window): boolean =>\n !canDisplayDeliverActivation(window) || activeToplevel() !== null;\n\nconst isTransientDescendant = (window: Gtk.Window, ancestor: Gtk.Window): boolean => {\n for (let parent = window.getTransientFor(); parent !== null; parent = parent.getTransientFor()) {\n if (parent === ancestor) {\n return true;\n }\n }\n\n return false;\n};\n\nconst isModalGrabHeldOver = (modal: Gtk.Window, window: Gtk.Window): boolean =>\n modal.getModal() &&\n modal !== window &&\n modal.getGroup() === window.getGroup() &&\n !isTransientDescendant(window, modal);\n\nconst isWindowBlockedByModal = (window: Gtk.Window): boolean =>\n mappedToplevels().some((toplevel) => isModalGrabHeldOver(toplevel, window));\n\nconst findPresentedWindowFailure = (window: Gtk.Window): string | null => {\n if (!isWindowAllocated(window)) {\n return WINDOW_NOT_ALLOCATED;\n }\n\n return isWindowActivated(window) ? null : WINDOW_NOT_ACTIVATED;\n};\n\nconst findRenderedWindowFailure = (window: Gtk.Window): string | null => {\n if (!isWindowAllocated(window)) {\n return WINDOW_NOT_ALLOCATED;\n }\n\n return isApplicationActivated(window) ? null : NO_WINDOW_ACTIVATED;\n};\n\nexport {\n activeToplevel,\n findPresentedWindowFailure,\n findRenderedWindowFailure,\n isWindowActivated,\n isWindowAllocated,\n isWindowBlockedByModal,\n mappedToplevels,\n};\n"]}
|
package/dist/within.d.ts
CHANGED
|
@@ -3,12 +3,13 @@ import type { Container } from "./traversal.js";
|
|
|
3
3
|
import type { BoundCustomQueries, QueryMap } from "./types.js";
|
|
4
4
|
/**
|
|
5
5
|
* Binds the built-in queries, and any custom queries, to a specific container
|
|
6
|
-
* so they search only within that scope.
|
|
6
|
+
* so they search only within that scope. Also exported as `getQueriesForElement`,
|
|
7
|
+
* which reads better in library code.
|
|
7
8
|
*
|
|
8
9
|
* @param container The scope the returned queries operate on.
|
|
9
10
|
* @param queries Optional custom queries to bind alongside the built-in ones.
|
|
10
11
|
* @returns The queries bound to the container.
|
|
11
12
|
*/
|
|
12
13
|
declare const within: <Q extends QueryMap = Record<never, never>>(container: Container, queries?: Q) => BoundQueries & BoundCustomQueries<Q>;
|
|
13
|
-
export { within };
|
|
14
|
+
export { within, within as getQueriesForElement };
|
|
14
15
|
//# sourceMappingURL=within.d.ts.map
|
package/dist/within.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"within.d.ts","sourceRoot":"","sources":["../src/within.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAc/D
|
|
1
|
+
{"version":3,"file":"within.d.ts","sourceRoot":"","sources":["../src/within.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAc/D;;;;;;;;GAQG;AACH,QAAA,MAAM,MAAM,GAAI,CAAC,SAAS,QAAQ,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EACrD,WAAW,SAAS,EACpB,UAAU,CAAC,KACZ,YAAY,GAAG,kBAAkB,CAAC,CAAC,CAGpC,CAAC;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,oBAAoB,EAAE,CAAC"}
|
package/dist/within.js
CHANGED
|
@@ -6,7 +6,8 @@ const bindCustomQueries = (customQueries, container) => {
|
|
|
6
6
|
};
|
|
7
7
|
/**
|
|
8
8
|
* Binds the built-in queries, and any custom queries, to a specific container
|
|
9
|
-
* so they search only within that scope.
|
|
9
|
+
* so they search only within that scope. Also exported as `getQueriesForElement`,
|
|
10
|
+
* which reads better in library code.
|
|
10
11
|
*
|
|
11
12
|
* @param container The scope the returned queries operate on.
|
|
12
13
|
* @param queries Optional custom queries to bind alongside the built-in ones.
|
|
@@ -16,5 +17,5 @@ const within = (container, queries) => ({
|
|
|
16
17
|
...bindCustomQueries(builtinQueries, container),
|
|
17
18
|
...(queries ? bindCustomQueries(queries, container) : {}),
|
|
18
19
|
});
|
|
19
|
-
export { within };
|
|
20
|
+
export { within, within as getQueriesForElement };
|
|
20
21
|
//# sourceMappingURL=within.js.map
|
package/dist/within.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"within.js","sourceRoot":"","sources":["../src/within.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,MAAM,SAAS,GACX,CAAiC,KAAsD,EAAE,SAAoB,EAAE,EAAE,CAC7G,CAAC,GAAG,IAAU,EAAU,EAAE,CACtB,KAAK,CAAC,SAAS,EAAE,GAAG,IAAI,CAAC,CAAC;AAEtC,MAAM,iBAAiB,GAAG,CAAqB,aAAgB,EAAE,SAAoB,EAAyB,EAAE;IAC5G,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,CAAU,CAAC,CAAC;IAEjH,OAAO,MAAM,CAAC,WAAW,CAAC,OAAO,CAA0B,CAAC;AAChE,CAAC,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"within.js","sourceRoot":"","sources":["../src/within.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,MAAM,SAAS,GACX,CAAiC,KAAsD,EAAE,SAAoB,EAAE,EAAE,CAC7G,CAAC,GAAG,IAAU,EAAU,EAAE,CACtB,KAAK,CAAC,SAAS,EAAE,GAAG,IAAI,CAAC,CAAC;AAEtC,MAAM,iBAAiB,GAAG,CAAqB,aAAgB,EAAE,SAAoB,EAAyB,EAAE;IAC5G,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,CAAU,CAAC,CAAC;IAEjH,OAAO,MAAM,CAAC,WAAW,CAAC,OAAO,CAA0B,CAAC;AAChE,CAAC,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,MAAM,GAAG,CACX,SAAoB,EACpB,OAAW,EACyB,EAAE,CAAC,CAAC;IACxC,GAAI,iBAAiB,CAAC,cAAc,EAAE,SAAS,CAAkB;IACjE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,CAAE,EAA4B,CAAC;CACvF,CAAC,CAAC;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,oBAAoB,EAAE,CAAC","sourcesContent":["import type { BoundQueries } from \"./bound-queries.js\";\nimport type { Container } from \"./traversal.js\";\nimport type { BoundCustomQueries, QueryMap } from \"./types.js\";\nimport { builtinQueries } from \"./queries.js\";\n\nconst bindQuery =\n <Args extends unknown[], Result>(query: (container: Container, ...args: Args) => Result, container: Container) =>\n (...args: Args): Result =>\n query(container, ...args);\n\nconst bindCustomQueries = <Q extends QueryMap>(customQueries: Q, container: Container): BoundCustomQueries<Q> => {\n const entries = Object.entries(customQueries).map(([key, query]) => [key, bindQuery(query, container)] as const);\n\n return Object.fromEntries(entries) as BoundCustomQueries<Q>;\n};\n\n/**\n * Binds the built-in queries, and any custom queries, to a specific container\n * so they search only within that scope. Also exported as `getQueriesForElement`,\n * which reads better in library code.\n *\n * @param container The scope the returned queries operate on.\n * @param queries Optional custom queries to bind alongside the built-in ones.\n * @returns The queries bound to the container.\n */\nconst within = <Q extends QueryMap = Record<never, never>>(\n container: Container,\n queries?: Q,\n): BoundQueries & BoundCustomQueries<Q> => ({\n ...(bindCustomQueries(builtinQueries, container) as BoundQueries),\n ...(queries ? bindCustomQueries(queries, container) : ({} as BoundCustomQueries<Q>)),\n});\n\nexport { within, within as getQueriesForElement };\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gtkx/testing",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Testing Library-style queries, user events, and screenshots for GTK4 widget trees rendered by GTKX",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"gtkx",
|
|
@@ -30,6 +30,10 @@
|
|
|
30
30
|
".": {
|
|
31
31
|
"types": "./dist/index.d.ts",
|
|
32
32
|
"default": "./dist/index.js"
|
|
33
|
+
},
|
|
34
|
+
"./internal": {
|
|
35
|
+
"types": "./dist/internal.d.ts",
|
|
36
|
+
"default": "./dist/internal.js"
|
|
33
37
|
}
|
|
34
38
|
},
|
|
35
39
|
"sideEffects": [
|
|
@@ -40,13 +44,25 @@
|
|
|
40
44
|
"dist",
|
|
41
45
|
"src"
|
|
42
46
|
],
|
|
47
|
+
"nx": {
|
|
48
|
+
"targets": {
|
|
49
|
+
"lint": {
|
|
50
|
+
"options": {
|
|
51
|
+
"cwd": ".",
|
|
52
|
+
"command": "eslint {projectRoot}"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
},
|
|
43
57
|
"engines": {
|
|
44
58
|
"node": ">=24"
|
|
45
59
|
},
|
|
46
60
|
"dependencies": {
|
|
47
|
-
"@
|
|
48
|
-
"@
|
|
49
|
-
"@gtkx/
|
|
61
|
+
"@vitest/expect": "^4.1.10",
|
|
62
|
+
"@vitest/pretty-format": "^4.1.10",
|
|
63
|
+
"@gtkx/runtime": "1.1.0",
|
|
64
|
+
"@gtkx/react": "1.1.0",
|
|
65
|
+
"@gtkx/utils": "1.1.0"
|
|
50
66
|
},
|
|
51
67
|
"peerDependencies": {
|
|
52
68
|
"@types/react": "^19.2",
|
|
@@ -54,10 +70,7 @@
|
|
|
54
70
|
},
|
|
55
71
|
"devDependencies": {
|
|
56
72
|
"@types/react": "^19.2.18",
|
|
57
|
-
"@
|
|
58
|
-
"vitest": "^4.1.10",
|
|
59
|
-
"@gtkx/vitest": "1.0.0-rc.4",
|
|
60
|
-
"@gtkx/config": "1.0.0-rc.4"
|
|
73
|
+
"@gtkx/config": "1.1.0"
|
|
61
74
|
},
|
|
62
75
|
"scripts": {
|
|
63
76
|
"release": "tsx ../../scripts/release-package.ts"
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
2
|
+
import { getHandle, t } from "@gtkx/runtime";
|
|
3
|
+
|
|
4
|
+
type CheckInt = (handle: unknown, attribute: number, expected: number) => string | null;
|
|
5
|
+
type CheckString = (handle: unknown, attribute: number, expected: string | null) => string | null;
|
|
6
|
+
type CheckDouble = (handle: unknown, attribute: number, expected: number) => string | null;
|
|
7
|
+
type CheckRelation = (...args: unknown[]) => string | null;
|
|
8
|
+
/** A value GTK holds for an accessible property: a string, a number, a token, or a boolean. */
|
|
9
|
+
type AccessibleAttributeValue = boolean | number | string;
|
|
10
|
+
type PropertyReader = (accessible: Gtk.Accessible, property: Gtk.AccessibleProperty) => AccessibleAttributeValue | null;
|
|
11
|
+
type NativeCall = (...inputs: unknown[]) => unknown;
|
|
12
|
+
type CheckArg = typeof DOUBLE_ARG | typeof INT_ARG | typeof OBJECT_ARG | typeof STRING_ARG;
|
|
13
|
+
|
|
14
|
+
const LIB = "libgtk-4.so.1";
|
|
15
|
+
const MAX_RELATION_TARGETS = 8;
|
|
16
|
+
const relationBindings: Map<number, CheckRelation> = new Map();
|
|
17
|
+
|
|
18
|
+
const REVERSE_RELATIONS: Partial<Record<Gtk.AccessibleRelation, Gtk.AccessibleRelation>> = {
|
|
19
|
+
[Gtk.AccessibleRelation.LABELLED_BY]: Gtk.AccessibleRelation.LABEL_FOR,
|
|
20
|
+
[Gtk.AccessibleRelation.DESCRIBED_BY]: Gtk.AccessibleRelation.DESCRIPTION_FOR,
|
|
21
|
+
[Gtk.AccessibleRelation.ERROR_MESSAGE]: Gtk.AccessibleRelation.ERROR_MESSAGE_FOR,
|
|
22
|
+
[Gtk.AccessibleRelation.CONTROLS]: Gtk.AccessibleRelation.CONTROLLED_BY,
|
|
23
|
+
[Gtk.AccessibleRelation.DETAILS]: Gtk.AccessibleRelation.DETAILS_FOR,
|
|
24
|
+
[Gtk.AccessibleRelation.FLOW_TO]: Gtk.AccessibleRelation.FLOW_FROM,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const UNDEFINED_VALUE = -1;
|
|
28
|
+
const INT_SENTINEL = -2_147_483_648;
|
|
29
|
+
const NUMBER_SENTINEL = -Number.MAX_VALUE;
|
|
30
|
+
const ACCESSIBLE_NUMBER_TOLERANCE = 0.001;
|
|
31
|
+
const BOOLEAN_DOMAIN = [0, 1];
|
|
32
|
+
const OPTIONAL_BOOLEAN_DOMAIN = [0, 1, UNDEFINED_VALUE];
|
|
33
|
+
const TRISTATE_DOMAIN = [Gtk.AccessibleTristate.FALSE, Gtk.AccessibleTristate.TRUE, Gtk.AccessibleTristate.MIXED];
|
|
34
|
+
|
|
35
|
+
const INVALID_DOMAIN = [
|
|
36
|
+
Gtk.AccessibleInvalidState.FALSE,
|
|
37
|
+
Gtk.AccessibleInvalidState.TRUE,
|
|
38
|
+
Gtk.AccessibleInvalidState.GRAMMAR,
|
|
39
|
+
Gtk.AccessibleInvalidState.SPELLING,
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
const STATE_DOMAINS: Partial<Record<Gtk.AccessibleState, number[]>> = {
|
|
43
|
+
[Gtk.AccessibleState.BUSY]: BOOLEAN_DOMAIN,
|
|
44
|
+
[Gtk.AccessibleState.CHECKED]: TRISTATE_DOMAIN,
|
|
45
|
+
[Gtk.AccessibleState.DISABLED]: BOOLEAN_DOMAIN,
|
|
46
|
+
[Gtk.AccessibleState.EXPANDED]: OPTIONAL_BOOLEAN_DOMAIN,
|
|
47
|
+
[Gtk.AccessibleState.HIDDEN]: BOOLEAN_DOMAIN,
|
|
48
|
+
[Gtk.AccessibleState.INVALID]: INVALID_DOMAIN,
|
|
49
|
+
[Gtk.AccessibleState.PRESSED]: TRISTATE_DOMAIN,
|
|
50
|
+
[Gtk.AccessibleState.SELECTED]: OPTIONAL_BOOLEAN_DOMAIN,
|
|
51
|
+
[Gtk.AccessibleState.VISITED]: OPTIONAL_BOOLEAN_DOMAIN,
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const AUTOCOMPLETE_DOMAIN = [
|
|
55
|
+
Gtk.AccessibleAutocomplete.NONE,
|
|
56
|
+
Gtk.AccessibleAutocomplete.INLINE,
|
|
57
|
+
Gtk.AccessibleAutocomplete.LIST,
|
|
58
|
+
Gtk.AccessibleAutocomplete.BOTH,
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
const ORIENTATION_DOMAIN = [Gtk.Orientation.HORIZONTAL, Gtk.Orientation.VERTICAL];
|
|
62
|
+
|
|
63
|
+
const SORT_DOMAIN = [
|
|
64
|
+
Gtk.AccessibleSort.NONE,
|
|
65
|
+
Gtk.AccessibleSort.ASCENDING,
|
|
66
|
+
Gtk.AccessibleSort.DESCENDING,
|
|
67
|
+
Gtk.AccessibleSort.OTHER,
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
const TOKEN_DOMAINS: Partial<Record<Gtk.AccessibleProperty, number[]>> = {
|
|
71
|
+
[Gtk.AccessibleProperty.AUTOCOMPLETE]: AUTOCOMPLETE_DOMAIN,
|
|
72
|
+
[Gtk.AccessibleProperty.ORIENTATION]: ORIENTATION_DOMAIN,
|
|
73
|
+
[Gtk.AccessibleProperty.SORT]: SORT_DOMAIN,
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const STRING_PROPERTIES: Set<Gtk.AccessibleProperty> = new Set<Gtk.AccessibleProperty>([
|
|
77
|
+
Gtk.AccessibleProperty.DESCRIPTION,
|
|
78
|
+
Gtk.AccessibleProperty.HELP_TEXT,
|
|
79
|
+
Gtk.AccessibleProperty.KEY_SHORTCUTS,
|
|
80
|
+
Gtk.AccessibleProperty.LABEL,
|
|
81
|
+
Gtk.AccessibleProperty.PLACEHOLDER,
|
|
82
|
+
Gtk.AccessibleProperty.ROLE_DESCRIPTION,
|
|
83
|
+
Gtk.AccessibleProperty.VALUE_TEXT,
|
|
84
|
+
]);
|
|
85
|
+
|
|
86
|
+
const BOOLEAN_PROPERTIES: Set<Gtk.AccessibleProperty> = new Set<Gtk.AccessibleProperty>([
|
|
87
|
+
Gtk.AccessibleProperty.HAS_POPUP,
|
|
88
|
+
Gtk.AccessibleProperty.MODAL,
|
|
89
|
+
Gtk.AccessibleProperty.MULTI_LINE,
|
|
90
|
+
Gtk.AccessibleProperty.MULTI_SELECTABLE,
|
|
91
|
+
Gtk.AccessibleProperty.READ_ONLY,
|
|
92
|
+
Gtk.AccessibleProperty.REQUIRED,
|
|
93
|
+
]);
|
|
94
|
+
|
|
95
|
+
const NUMBER_PROPERTIES: Set<Gtk.AccessibleProperty> = new Set<Gtk.AccessibleProperty>([
|
|
96
|
+
Gtk.AccessibleProperty.VALUE_MAX,
|
|
97
|
+
Gtk.AccessibleProperty.VALUE_MIN,
|
|
98
|
+
Gtk.AccessibleProperty.VALUE_NOW,
|
|
99
|
+
]);
|
|
100
|
+
|
|
101
|
+
const OBJECT_ARG = { type: t.object("borrowed") };
|
|
102
|
+
const INT_ARG = { type: t.int32 };
|
|
103
|
+
const DOUBLE_ARG = { type: t.float64 };
|
|
104
|
+
const STRING_ARG = { type: t.string("borrowed") };
|
|
105
|
+
const CHECK_PROPERTY = "gtk_test_accessible_check_property";
|
|
106
|
+
const checkStateInt = buildAccessibleCheck("gtk_test_accessible_check_state", [INT_ARG]) as CheckInt;
|
|
107
|
+
const checkPropertyInt = buildAccessibleCheck(CHECK_PROPERTY, [INT_ARG]) as CheckInt;
|
|
108
|
+
const checkPropertyDouble = buildAccessibleCheck(CHECK_PROPERTY, [DOUBLE_ARG]) as CheckDouble;
|
|
109
|
+
const checkPropertyString = buildAccessibleCheck(CHECK_PROPERTY, [STRING_ARG]) as CheckString;
|
|
110
|
+
|
|
111
|
+
function buildAccessibleCheck(symbol: string, varargs: CheckArg[]): NativeCall {
|
|
112
|
+
return t.fn(LIB, symbol, {
|
|
113
|
+
args: [OBJECT_ARG, INT_ARG, ...varargs],
|
|
114
|
+
returns: t.string("full"),
|
|
115
|
+
fixedArgCount: 2,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const buildRelationBinding = (targetCount: number): CheckRelation => {
|
|
120
|
+
const targets = Array.from({ length: targetCount + 1 }, () => OBJECT_ARG);
|
|
121
|
+
|
|
122
|
+
return buildAccessibleCheck("gtk_test_accessible_check_relation", targets) as CheckRelation;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const relationBindingFor = (targetCount: number): CheckRelation => {
|
|
126
|
+
const cached = relationBindings.get(targetCount);
|
|
127
|
+
|
|
128
|
+
if (cached !== undefined) {
|
|
129
|
+
return cached;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const built = buildRelationBinding(targetCount);
|
|
133
|
+
relationBindings.set(targetCount, built);
|
|
134
|
+
|
|
135
|
+
return built;
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const isRelationExactly = (
|
|
139
|
+
accessible: Gtk.Accessible,
|
|
140
|
+
relation: Gtk.AccessibleRelation,
|
|
141
|
+
candidate: Gtk.Accessible,
|
|
142
|
+
targetCount: number,
|
|
143
|
+
): boolean => {
|
|
144
|
+
const call = relationBindingFor(targetCount);
|
|
145
|
+
const repeated = Array.from({ length: targetCount }, () => getHandle(candidate));
|
|
146
|
+
|
|
147
|
+
return call(getHandle(accessible), relation, ...repeated, null) === null;
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const hasRelationSize = (
|
|
151
|
+
accessible: Gtk.Accessible,
|
|
152
|
+
relation: Gtk.AccessibleRelation,
|
|
153
|
+
candidates: Gtk.Accessible[],
|
|
154
|
+
size: number,
|
|
155
|
+
): boolean => candidates.some((candidate) => isRelationExactly(accessible, relation, candidate, size));
|
|
156
|
+
|
|
157
|
+
const findRelationSize = (
|
|
158
|
+
accessible: Gtk.Accessible,
|
|
159
|
+
relation: Gtk.AccessibleRelation,
|
|
160
|
+
candidates: Gtk.Accessible[],
|
|
161
|
+
): number => {
|
|
162
|
+
for (let size = 1; size <= MAX_RELATION_TARGETS; size += 1) {
|
|
163
|
+
if (hasRelationSize(accessible, relation, candidates, size)) {
|
|
164
|
+
return size;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return 0;
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
const possibleTargets = (relation: Gtk.AccessibleRelation, candidates: Gtk.Accessible[]): Gtk.Accessible[] => {
|
|
172
|
+
const reverse = REVERSE_RELATIONS[relation];
|
|
173
|
+
|
|
174
|
+
if (reverse === undefined) {
|
|
175
|
+
return candidates;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return candidates.filter((candidate) => Gtk.testAccessibleHasRelation(candidate, reverse));
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const readAccessibleRelation = (
|
|
182
|
+
accessible: Gtk.Accessible,
|
|
183
|
+
relation: Gtk.AccessibleRelation,
|
|
184
|
+
pool: Gtk.Accessible[],
|
|
185
|
+
): Gtk.Accessible[] => {
|
|
186
|
+
if (!Gtk.testAccessibleHasRelation(accessible, relation)) {
|
|
187
|
+
return [];
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const candidates = possibleTargets(relation, pool);
|
|
191
|
+
const size = findRelationSize(accessible, relation, candidates);
|
|
192
|
+
|
|
193
|
+
if (size === 0) {
|
|
194
|
+
return [];
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return candidates.filter((candidate) => isRelationExactly(accessible, relation, candidate, size));
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
const memberOfDomain = (check: CheckInt, handle: unknown, attribute: number, domain: number[]): number | null => {
|
|
201
|
+
for (const candidate of domain) {
|
|
202
|
+
if (check(handle, attribute, candidate) === null) {
|
|
203
|
+
return candidate;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return null;
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
const readAccessibleState = (accessible: Gtk.Accessible, state: Gtk.AccessibleState): number | null => {
|
|
211
|
+
const domain = STATE_DOMAINS[state];
|
|
212
|
+
|
|
213
|
+
if (domain === undefined || !Gtk.testAccessibleHasState(accessible, state)) {
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const member = memberOfDomain(checkStateInt, getHandle(accessible), state, domain);
|
|
218
|
+
|
|
219
|
+
return member === UNDEFINED_VALUE ? null : member;
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
const readAccessibleFlag = (accessible: Gtk.Accessible, state: Gtk.AccessibleState): boolean | null => {
|
|
223
|
+
const value = readAccessibleState(accessible, state);
|
|
224
|
+
|
|
225
|
+
return value === null ? null : value === 1;
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
const readAccessibleString = (accessible: Gtk.Accessible, property: Gtk.AccessibleProperty): string | null => {
|
|
229
|
+
if (!Gtk.testAccessibleHasProperty(accessible, property)) {
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return checkPropertyString(getHandle(accessible), property, null);
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
const readAccessibleToken = (
|
|
237
|
+
accessible: Gtk.Accessible,
|
|
238
|
+
property: Gtk.AccessibleProperty,
|
|
239
|
+
domain: number[],
|
|
240
|
+
): number | null => {
|
|
241
|
+
if (!Gtk.testAccessibleHasProperty(accessible, property)) {
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return memberOfDomain(checkPropertyInt, getHandle(accessible), property, domain);
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
const readAccessibleBooleanProperty = (
|
|
249
|
+
accessible: Gtk.Accessible,
|
|
250
|
+
property: Gtk.AccessibleProperty,
|
|
251
|
+
): boolean | null => {
|
|
252
|
+
const member = readAccessibleToken(accessible, property, BOOLEAN_DOMAIN);
|
|
253
|
+
|
|
254
|
+
return member === null ? null : member === 1;
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
const readAgainstSentinel = (
|
|
258
|
+
check: CheckDouble,
|
|
259
|
+
sentinel: number,
|
|
260
|
+
accessible: Gtk.Accessible,
|
|
261
|
+
property: Gtk.AccessibleProperty,
|
|
262
|
+
): number | null => {
|
|
263
|
+
if (!Gtk.testAccessibleHasProperty(accessible, property)) {
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const reported = check(getHandle(accessible), property, sentinel);
|
|
268
|
+
|
|
269
|
+
return reported === null ? sentinel : Number(reported);
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
const readAccessibleInt = (accessible: Gtk.Accessible, property: Gtk.AccessibleProperty): number | null =>
|
|
273
|
+
readAgainstSentinel(checkPropertyInt, INT_SENTINEL, accessible, property);
|
|
274
|
+
|
|
275
|
+
const readAccessibleNumber = (accessible: Gtk.Accessible, property: Gtk.AccessibleProperty): number | null =>
|
|
276
|
+
readAgainstSentinel(checkPropertyDouble, NUMBER_SENTINEL, accessible, property);
|
|
277
|
+
|
|
278
|
+
const isAccessibleNumberProperty = (property: Gtk.AccessibleProperty): boolean => NUMBER_PROPERTIES.has(property);
|
|
279
|
+
|
|
280
|
+
const isAccessibleNumberMatch = (
|
|
281
|
+
accessible: Gtk.Accessible,
|
|
282
|
+
property: Gtk.AccessibleProperty,
|
|
283
|
+
expected: number,
|
|
284
|
+
): boolean =>
|
|
285
|
+
Gtk.testAccessibleHasProperty(accessible, property) &&
|
|
286
|
+
checkPropertyDouble(getHandle(accessible), property, expected) === null;
|
|
287
|
+
|
|
288
|
+
const tokenReaderFor =
|
|
289
|
+
(domain: number[]): PropertyReader =>
|
|
290
|
+
(accessible, property) =>
|
|
291
|
+
readAccessibleToken(accessible, property, domain);
|
|
292
|
+
|
|
293
|
+
const propertyReaderFor = (property: Gtk.AccessibleProperty): PropertyReader => {
|
|
294
|
+
const domain = TOKEN_DOMAINS[property];
|
|
295
|
+
|
|
296
|
+
if (domain !== undefined) {
|
|
297
|
+
return tokenReaderFor(domain);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (STRING_PROPERTIES.has(property)) {
|
|
301
|
+
return readAccessibleString;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if (BOOLEAN_PROPERTIES.has(property)) {
|
|
305
|
+
return readAccessibleBooleanProperty;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if (NUMBER_PROPERTIES.has(property)) {
|
|
309
|
+
return readAccessibleNumber;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return readAccessibleInt;
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
const readAccessibleProperty = (
|
|
316
|
+
accessible: Gtk.Accessible,
|
|
317
|
+
property: Gtk.AccessibleProperty,
|
|
318
|
+
): AccessibleAttributeValue | null => propertyReaderFor(property)(accessible, property);
|
|
319
|
+
|
|
320
|
+
export {
|
|
321
|
+
ACCESSIBLE_NUMBER_TOLERANCE,
|
|
322
|
+
isAccessibleNumberMatch,
|
|
323
|
+
isAccessibleNumberProperty,
|
|
324
|
+
readAccessibleBooleanProperty,
|
|
325
|
+
readAccessibleFlag,
|
|
326
|
+
readAccessibleInt,
|
|
327
|
+
readAccessibleNumber,
|
|
328
|
+
readAccessibleProperty,
|
|
329
|
+
readAccessibleRelation,
|
|
330
|
+
readAccessibleState,
|
|
331
|
+
readAccessibleString,
|
|
332
|
+
type AccessibleAttributeValue,
|
|
333
|
+
};
|
package/src/act.ts
CHANGED