@gtkx/testing 1.4.0 → 1.5.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 CHANGED
@@ -98,7 +98,7 @@ GTK4 is mature, and GtkBuilder XML can lay out a static interface, but nothing r
98
98
  - a React reconciler that exposes every GObject as a JSX element,
99
99
  - a CLI for scaffolding, development, and production builds,
100
100
  - a dev server with Fast Refresh that patches your running UI in place,
101
- - CSS-in-JS styling, React Spring animations, React Navigation stack, tab, drawer, and split view navigators, and high-level list, grid, and dialog components,
101
+ - CSS-in-JS styling, React Hook Form-powered Adwaita controls, gettext-backed react-i18next localization, React Spring animations, React Navigation stack, tab, drawer, and split view navigators, and high-level list, grid, and dialog components,
102
102
  - a Testing Library-style API for querying and driving your widgets in tests,
103
103
  - and a Model Context Protocol (MCP) server that exposes your live app to AI agents.
104
104
 
package/dist/act.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"act.d.ts","sourceRoot":"","sources":["../src/act.ts"],"names":[],"mappings":"AAEA,OAAO,CAAC,MAAM,CAAC;IACX,IAAI,wBAAwB,EAAE,OAAO,GAAG,SAAS,CAAC;CACrD;AAED,+EAA+E;AAC/E,KAAK,WAAW,CAAC,CAAC,IAAI,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;AAC/C,qGAAqG;AACrG,KAAK,iBAAiB,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC;AAGzE;;;;;;GAMG;AACH,QAAA,MAAM,GAAG,EAAE,iBAA+D,CAAC;AAU3E,QAAA,MAAM,wBAAwB,QAAO,OAAO,GAAG,SAAqD,CAAC;AAErG,QAAA,MAAM,wBAAwB,GAAI,OAAO,OAAO,GAAG,SAAS,KAAG,IAE9D,CAAC;AAaF,QAAA,MAAM,qBAAqB,GAAI,CAAC,EAAE,UAAU,OAAO,EAAE,IAAI,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,KAAG,OAAO,CAAC,CAAC,CAkB5F,CAAC;AAUF,QAAA,MAAM,QAAQ,GAAU,UAAU,MAAM,OAAO,KAAG,OAAO,CAAC,IAAI,CAE7D,CAAC;AAEF,OAAO,EAAE,GAAG,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,QAAQ,EAAE,wBAAwB,EAAE,CAAC"}
1
+ {"version":3,"file":"act.d.ts","sourceRoot":"","sources":["../src/act.ts"],"names":[],"mappings":"AAEA,OAAO,CAAC,MAAM,CAAC;IACX,IAAI,wBAAwB,EAAE,OAAO,GAAG,SAAS,CAAC;CACrD;AAED,+EAA+E;AAC/E,KAAK,WAAW,CAAC,CAAC,IAAI,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;AAC/C,qGAAqG;AACrG,KAAK,iBAAiB,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC;AAGzE;;;;;;GAMG;AACH,QAAA,MAAM,GAAG,EAAE,iBAA+D,CAAC;AAE3E,QAAA,MAAM,wBAAwB,QAAO,OAAO,GAAG,SAAgD,CAAC;AAEhG,QAAA,MAAM,wBAAwB,GAAI,OAAO,OAAO,GAAG,SAAS,KAAG,IAE9D,CAAC;AAaF,QAAA,MAAM,qBAAqB,GAAI,CAAC,EAAE,UAAU,OAAO,EAAE,IAAI,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,KAAG,OAAO,CAAC,CAAC,CAkB5F,CAAC;AAUF,QAAA,MAAM,QAAQ,GAAU,UAAU,MAAM,OAAO,KAAG,OAAO,CAAC,IAAI,CAE7D,CAAC;AAEF,OAAO,EAAE,GAAG,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,QAAQ,EAAE,wBAAwB,EAAE,CAAC"}
package/dist/act.js CHANGED
@@ -8,15 +8,9 @@ const actImplementation = reactAct;
8
8
  * @returns A promise that resolves with the callback's result after updates flush.
9
9
  */
10
10
  const act = withGlobalActEnvironment(actImplementation);
11
- const getGlobalThis = () => {
12
- if (typeof globalThis !== "undefined") {
13
- return globalThis;
14
- }
15
- throw new Error("unable to locate global object");
16
- };
17
- const getIsReactActEnvironment = () => getGlobalThis().IS_REACT_ACT_ENVIRONMENT;
11
+ const getIsReactActEnvironment = () => globalThis.IS_REACT_ACT_ENVIRONMENT;
18
12
  const setIsReactActEnvironment = (value) => {
19
- getGlobalThis().IS_REACT_ACT_ENVIRONMENT = value;
13
+ Reflect.set(globalThis, "IS_REACT_ACT_ENVIRONMENT", value);
20
14
  };
21
15
  const isThenable = (value) => value !== null && typeof value === "object" && typeof value.then === "function";
22
16
  const restoreAfter = async (result, previous) => {
package/dist/act.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"act.js","sourceRoot":"","sources":["../src/act.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,IAAI,QAAQ,EAAE,MAAM,OAAO,CAAC;AAWxC,MAAM,iBAAiB,GAAsB,QAAQ,CAAC;AACtD;;;;;;GAMG;AACH,MAAM,GAAG,GAAsB,wBAAwB,CAAC,iBAAiB,CAAC,CAAC;AAE3E,MAAM,aAAa,GAAG,GAAsB,EAAE;IAC1C,IAAI,OAAO,UAAU,KAAK,WAAW,EAAE,CAAC;QACpC,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;AACtD,CAAC,CAAC;AAEF,MAAM,wBAAwB,GAAG,GAAwB,EAAE,CAAC,aAAa,EAAE,CAAC,wBAAwB,CAAC;AAErG,MAAM,wBAAwB,GAAG,CAAC,KAA0B,EAAQ,EAAE;IAClE,aAAa,EAAE,CAAC,wBAAwB,GAAG,KAAK,CAAC;AACrD,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,CAAI,KAAc,EAA2B,EAAE,CAC9D,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAQ,KAAwB,CAAC,IAAI,KAAK,UAAU,CAAC;AAExG,MAAM,YAAY,GAAG,KAAK,EAAK,MAAsB,EAAE,QAA6B,EAAc,EAAE;IAChG,IAAI,CAAC;QACD,OAAO,MAAM,MAAM,CAAC;IACxB,CAAC;YAAS,CAAC;QACP,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,CAAI,QAAiB,EAAE,EAA4B,EAAc,EAAE;IAC7F,MAAM,sBAAsB,GAAG,wBAAwB,EAAE,CAAC;IAC1D,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IAEnC,IAAI,CAAC;QACD,MAAM,MAAM,GAAuB,EAAE,EAAE,CAAC;QAExC,IAAI,UAAU,CAAI,MAAM,CAAC,EAAE,CAAC;YACxB,OAAO,YAAY,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;QACxD,CAAC;QAED,wBAAwB,CAAC,sBAAsB,CAAC,CAAC;QAEjD,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,wBAAwB,CAAC,sBAAsB,CAAC,CAAC;QACjD,MAAM,KAAK,CAAC;IAChB,CAAC;AACL,CAAC,CAAC;AAEF,SAAS,wBAAwB,CAAC,iBAAoC;IAClE,OAAO,CAAI,QAAwB,EAAkB,EAAE;QACnD,MAAM,OAAO,GAAG,qBAAqB,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAEvF,OAAO,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,QAAQ,GAAG,KAAK,EAAE,QAAuB,EAAiB,EAAE;IAC9D,MAAM,GAAG,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;AAChC,CAAC,CAAC;AAEF,OAAO,EAAE,GAAG,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,QAAQ,EAAE,wBAAwB,EAAE,CAAC","sourcesContent":["import { act as reactAct } from \"react\";\n\ndeclare global {\n var IS_REACT_ACT_ENVIRONMENT: boolean | undefined;\n}\n\n/** Work run inside the act environment, either synchronous or asynchronous. */\ntype ActCallback<T> = () => T | PromiseLike<T>;\n/** Runs a callback inside React's act environment and settles with its result once updates flush. */\ntype ActImplementation = <T>(callback: ActCallback<T>) => PromiseLike<T>;\n\nconst actImplementation: ActImplementation = reactAct;\n/**\n * Runs a callback inside React's act environment, flushing pending state\n * updates and effects, and resolves once the work has settled.\n *\n * @param callback Work to run within the act environment.\n * @returns A promise that resolves with the callback's result after updates flush.\n */\nconst act: ActImplementation = withGlobalActEnvironment(actImplementation);\n\nconst getGlobalThis = (): typeof globalThis => {\n if (typeof globalThis !== \"undefined\") {\n return globalThis;\n }\n\n throw new Error(\"unable to locate global object\");\n};\n\nconst getIsReactActEnvironment = (): boolean | undefined => getGlobalThis().IS_REACT_ACT_ENVIRONMENT;\n\nconst setIsReactActEnvironment = (value: boolean | undefined): void => {\n getGlobalThis().IS_REACT_ACT_ENVIRONMENT = value;\n};\n\nconst isThenable = <T>(value: unknown): value is PromiseLike<T> =>\n value !== null && typeof value === \"object\" && typeof (value as PromiseLike<T>).then === \"function\";\n\nconst restoreAfter = async <T>(result: PromiseLike<T>, previous: boolean | undefined): Promise<T> => {\n try {\n return await result;\n } finally {\n setIsReactActEnvironment(previous);\n }\n};\n\nconst runWithActEnvironment = <T>(isForced: boolean, fn: () => T | PromiseLike<T>): Promise<T> => {\n const previousActEnvironment = getIsReactActEnvironment();\n setIsReactActEnvironment(isForced);\n\n try {\n const result: T | PromiseLike<T> = fn();\n\n if (isThenable<T>(result)) {\n return restoreAfter(result, previousActEnvironment);\n }\n\n setIsReactActEnvironment(previousActEnvironment);\n\n return Promise.resolve(result);\n } catch (error) {\n setIsReactActEnvironment(previousActEnvironment);\n throw error;\n }\n};\n\nfunction withGlobalActEnvironment(actImplementation: ActImplementation): ActImplementation {\n return <T>(callback: ActCallback<T>): PromiseLike<T> => {\n const settled = runWithActEnvironment(true, () => actImplementation(() => callback()));\n\n return Promise.resolve(settled);\n };\n}\n\nconst runInAct = async (callback: () => unknown): Promise<void> => {\n await act(() => callback());\n};\n\nexport { act, getIsReactActEnvironment, runWithActEnvironment, runInAct, setIsReactActEnvironment };\n"]}
1
+ {"version":3,"file":"act.js","sourceRoot":"","sources":["../src/act.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,IAAI,QAAQ,EAAE,MAAM,OAAO,CAAC;AAWxC,MAAM,iBAAiB,GAAsB,QAAQ,CAAC;AACtD;;;;;;GAMG;AACH,MAAM,GAAG,GAAsB,wBAAwB,CAAC,iBAAiB,CAAC,CAAC;AAE3E,MAAM,wBAAwB,GAAG,GAAwB,EAAE,CAAC,UAAU,CAAC,wBAAwB,CAAC;AAEhG,MAAM,wBAAwB,GAAG,CAAC,KAA0B,EAAQ,EAAE;IAClE,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,0BAA0B,EAAE,KAAK,CAAC,CAAC;AAC/D,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,CAAI,KAAc,EAA2B,EAAE,CAC9D,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAQ,KAAwB,CAAC,IAAI,KAAK,UAAU,CAAC;AAExG,MAAM,YAAY,GAAG,KAAK,EAAK,MAAsB,EAAE,QAA6B,EAAc,EAAE;IAChG,IAAI,CAAC;QACD,OAAO,MAAM,MAAM,CAAC;IACxB,CAAC;YAAS,CAAC;QACP,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,CAAI,QAAiB,EAAE,EAA4B,EAAc,EAAE;IAC7F,MAAM,sBAAsB,GAAG,wBAAwB,EAAE,CAAC;IAC1D,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IAEnC,IAAI,CAAC;QACD,MAAM,MAAM,GAAuB,EAAE,EAAE,CAAC;QAExC,IAAI,UAAU,CAAI,MAAM,CAAC,EAAE,CAAC;YACxB,OAAO,YAAY,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;QACxD,CAAC;QAED,wBAAwB,CAAC,sBAAsB,CAAC,CAAC;QAEjD,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,wBAAwB,CAAC,sBAAsB,CAAC,CAAC;QACjD,MAAM,KAAK,CAAC;IAChB,CAAC;AACL,CAAC,CAAC;AAEF,SAAS,wBAAwB,CAAC,iBAAoC;IAClE,OAAO,CAAI,QAAwB,EAAkB,EAAE;QACnD,MAAM,OAAO,GAAG,qBAAqB,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAEvF,OAAO,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,QAAQ,GAAG,KAAK,EAAE,QAAuB,EAAiB,EAAE;IAC9D,MAAM,GAAG,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;AAChC,CAAC,CAAC;AAEF,OAAO,EAAE,GAAG,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,QAAQ,EAAE,wBAAwB,EAAE,CAAC","sourcesContent":["import { act as reactAct } from \"react\";\n\ndeclare global {\n var IS_REACT_ACT_ENVIRONMENT: boolean | undefined;\n}\n\n/** Work run inside the act environment, either synchronous or asynchronous. */\ntype ActCallback<T> = () => T | PromiseLike<T>;\n/** Runs a callback inside React's act environment and settles with its result once updates flush. */\ntype ActImplementation = <T>(callback: ActCallback<T>) => PromiseLike<T>;\n\nconst actImplementation: ActImplementation = reactAct;\n/**\n * Runs a callback inside React's act environment, flushing pending state\n * updates and effects, and resolves once the work has settled.\n *\n * @param callback Work to run within the act environment.\n * @returns A promise that resolves with the callback's result after updates flush.\n */\nconst act: ActImplementation = withGlobalActEnvironment(actImplementation);\n\nconst getIsReactActEnvironment = (): boolean | undefined => globalThis.IS_REACT_ACT_ENVIRONMENT;\n\nconst setIsReactActEnvironment = (value: boolean | undefined): void => {\n Reflect.set(globalThis, \"IS_REACT_ACT_ENVIRONMENT\", value);\n};\n\nconst isThenable = <T>(value: unknown): value is PromiseLike<T> =>\n value !== null && typeof value === \"object\" && typeof (value as PromiseLike<T>).then === \"function\";\n\nconst restoreAfter = async <T>(result: PromiseLike<T>, previous: boolean | undefined): Promise<T> => {\n try {\n return await result;\n } finally {\n setIsReactActEnvironment(previous);\n }\n};\n\nconst runWithActEnvironment = <T>(isForced: boolean, fn: () => T | PromiseLike<T>): Promise<T> => {\n const previousActEnvironment = getIsReactActEnvironment();\n setIsReactActEnvironment(isForced);\n\n try {\n const result: T | PromiseLike<T> = fn();\n\n if (isThenable<T>(result)) {\n return restoreAfter(result, previousActEnvironment);\n }\n\n setIsReactActEnvironment(previousActEnvironment);\n\n return Promise.resolve(result);\n } catch (error) {\n setIsReactActEnvironment(previousActEnvironment);\n throw error;\n }\n};\n\nfunction withGlobalActEnvironment(actImplementation: ActImplementation): ActImplementation {\n return <T>(callback: ActCallback<T>): PromiseLike<T> => {\n const settled = runWithActEnvironment(true, () => actImplementation(() => callback()));\n\n return Promise.resolve(settled);\n };\n}\n\nconst runInAct = async (callback: () => unknown): Promise<void> => {\n await act(() => callback());\n};\n\nexport { act, getIsReactActEnvironment, runWithActEnvironment, runInAct, setIsReactActEnvironment };\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"pretty-widget.d.ts","sourceRoot":"","sources":["../src/pretty-widget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAEpC,OAAO,EAAuC,KAAK,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAEtG,OAAO,EAAE,KAAK,SAAS,EAAkC,MAAM,gBAAgB,CAAC;AAIhF,wFAAwF;AACxF,KAAK,gBAAgB,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,KAAK,MAAM,CAAC;AAEvD;;;GAGG;AACH,KAAK,mBAAmB,GAAG;IACvB,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uFAAuF;IACvF,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,0DAA0D;IAC1D,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,uFAAuF;IACvF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gGAAgG;IAChG,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;CAC7C,CAAC;AAqMF;;;;;;;GAOG;AACH,QAAA,MAAM,YAAY,GAAI,WAAW,SAAS,EAAE,UAAS,mBAAwB,KAAG,MAmB/E,CAAC;AAEF;;;;;GAKG;AACH,QAAA,MAAM,SAAS,GAAI,WAAW,SAAS,GAAG,SAAS,EAAE,EAAE,UAAU,mBAAmB,KAAG,IAMtF,CAAC;AAEF,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,CAAC"}
1
+ {"version":3,"file":"pretty-widget.d.ts","sourceRoot":"","sources":["../src/pretty-widget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAEpC,OAAO,EAAuC,KAAK,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAEtG,OAAO,EAAE,KAAK,SAAS,EAAkC,MAAM,gBAAgB,CAAC;AAIhF,wFAAwF;AACxF,KAAK,gBAAgB,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,KAAK,MAAM,CAAC;AAEvD;;;GAGG;AACH,KAAK,mBAAmB,GAAG;IACvB,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uFAAuF;IACvF,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,0DAA0D;IAC1D,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,uFAAuF;IACvF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gGAAgG;IAChG,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;CAC7C,CAAC;AAiMF;;;;;;;GAOG;AACH,QAAA,MAAM,YAAY,GAAI,WAAW,SAAS,EAAE,UAAS,mBAAwB,KAAG,MAmB/E,CAAC;AAEF;;;;;GAKG;AACH,QAAA,MAAM,SAAS,GAAI,WAAW,SAAS,GAAG,SAAS,EAAE,EAAE,UAAU,mBAAmB,KAAG,IAMtF,CAAC;AAEF,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,CAAC"}
@@ -30,9 +30,6 @@ const buildAttrs = (widget, getId) => {
30
30
  return [...idAttrs, ...otherAttrs];
31
31
  };
32
32
  const isHighlightSupported = () => {
33
- if (typeof process === "undefined") {
34
- return false;
35
- }
36
33
  if (process.env.COLORS === "false" || process.env.NO_COLOR) {
37
34
  return false;
38
35
  }
@@ -1 +1 @@
1
- {"version":3,"file":"pretty-widget.js","sourceRoot":"","sources":["../src/pretty-widget.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Gtk from \"@gtkx/gi/gtk\";\nimport { sortStringsBy } from \"@gtkx/utils\";\nimport { type Config, format, type NewPlugin, type PrettyFormatOptions } from \"@vitest/pretty-format\";\nimport { formatRole } from \"./role-helpers.js\";\nimport { type Container, descendants, isOnScreen, roots } from \"./traversal.js\";\nimport { getWidgetText } from \"./widget-accessible-properties.js\";\nimport { getTypeTag } from \"./widget-getters.js\";\n\n/** Produces the value of the `id` attribute printed first on a widget's opening tag. */\ntype WidgetIdResolver = (widget: Gtk.Widget) => string;\n\n/**\n * Options controlling how a widget tree is rendered to a string by\n * {@link prettyWidget} and {@link logWidget}.\n */\ntype PrettyWidgetOptions = {\n /** Truncates the output once it exceeds this many characters. */\n maxLength?: number;\n /** Whether to apply ANSI color highlighting; defaults to the terminal capabilities. */\n shouldHighlight?: boolean;\n /** Resolves an `id` attribute to show for each widget. */\n getId?: WidgetIdResolver;\n /** Stops descending past this depth, replacing deeper children with a summary line. */\n maxDepth?: number;\n /** Forwarded to pretty-format, which does the printing; `indent` and `min` shape the layout. */\n prettyFormatOptions?: PrettyFormatOptions;\n};\n\ntype Color = { open: string; close: string };\n\ntype FormatContext = {\n getId: WidgetIdResolver | undefined;\n config: Config;\n maxDepth: number | undefined;\n};\n\nconst DEFAULT_MAX_LENGTH = 7000;\n\nconst buildAttrs = (widget: Gtk.Widget, getId: WidgetIdResolver | undefined): [string, string][] => {\n const attrs: [string, string][] = [];\n\n if (getId) {\n attrs.push([\"id\", getId(widget)]);\n }\n\n const name = widget.getName();\n\n if (name) {\n attrs.push([\"name\", name]);\n }\n\n attrs.push([\"role\", formatRole(widget.getAccessibleRole())]);\n\n if (!widget.getSensitive()) {\n attrs.push([\"accessible-disabled\", \"true\"]);\n }\n\n if (!widget.getVisible()) {\n attrs.push([\"accessible-hidden\", \"true\"]);\n }\n\n if (!isOnScreen(widget)) {\n attrs.push([\"mapped\", \"false\"]);\n }\n\n const idAttrs = attrs.filter(([key]) => key === \"id\");\n\n const otherAttrs = sortStringsBy(\n attrs.filter(([key]) => key !== \"id\"),\n ([key]) => key,\n );\n\n return [...idAttrs, ...otherAttrs];\n};\n\nconst isHighlightSupported = (): boolean => {\n if (typeof process === \"undefined\") {\n return false;\n }\n\n if (process.env.COLORS === \"false\" || process.env.NO_COLOR) {\n return false;\n }\n\n if (process.env.COLORS === \"true\" || process.env.FORCE_COLOR) {\n return true;\n }\n\n return process.stdout.isTTY;\n};\n\nconst paint = (color: Color, text: string): string => `${color.open}${text}${color.close}`;\nconst escapeAttrValue = (value: string): string => value.replaceAll('\"', \"&quot;\");\n\nconst formatAttr = (key: string, value: string, colors: Config[\"colors\"]): string => {\n const quoted = `\"${escapeAttrValue(value)}\"`;\n\n return ` ${paint(colors.prop, key)}=${paint(colors.value, quoted)}`;\n};\n\nconst formatAttrs = (attrs: [string, string][], colors: Config[\"colors\"]): string =>\n attrs.map(([key, value]) => formatAttr(key, value, colors)).join(\"\");\n\nconst countChildren = (widget: Gtk.Widget): number => {\n let count = 0;\n let child = widget.getFirstChild();\n\n while (child) {\n count += 1;\n child = child.getNextSibling();\n }\n\n return count;\n};\n\nconst depthLimitReason = (widget: Gtk.Widget, getId: WidgetIdResolver | undefined): string => {\n const hint = getId ? ` (pass rootId=\"${getId(widget)}\" or raise maxDepth to expand)` : \"\";\n\n return `hidden${hint}`;\n};\n\nconst hasMappedDescendant = (widget: Gtk.Widget): boolean => {\n for (const descendant of descendants(widget)) {\n if (isOnScreen(descendant)) {\n return true;\n }\n }\n\n return false;\n};\n\nconst collapseReasonFor = (widget: Gtk.Widget, depth: number, ctx: FormatContext): string | null => {\n if (!widget.getFirstChild()) {\n return null;\n }\n\n if (!isOnScreen(widget) && !hasMappedDescendant(widget)) {\n return \"not mapped\";\n }\n\n if (ctx.maxDepth !== undefined && depth >= ctx.maxDepth) {\n return depthLimitReason(widget, ctx.getId);\n }\n\n return null;\n};\n\nconst formatCollapsedChildrenLine = (\n widget: Gtk.Widget,\n indentation: string,\n config: Config,\n reason: string,\n): string => {\n const count = countChildren(widget);\n const plural = count === 1 ? \"\" : \"s\";\n const summary = `… ${String(count)} child widget${plural} ${reason}`;\n\n return `${indentation}${config.indent}${paint(config.colors.tag, summary)}${config.spacingOuter}`;\n};\n\nconst formatChildren = (widget: Gtk.Widget, indentation: string, depth: number, ctx: FormatContext): string => {\n let output = \"\";\n let child = widget.getFirstChild();\n\n while (child) {\n output += formatWidget(child, indentation + ctx.config.indent, depth + 1, ctx);\n child = child.getNextSibling();\n }\n\n return output;\n};\n\nconst formatBody = (widget: Gtk.Widget, indentation: string, depth: number, ctx: FormatContext): string => {\n const collapseReason = collapseReasonFor(widget, depth, ctx);\n\n if (collapseReason === null) {\n return formatChildren(widget, indentation, depth, ctx);\n }\n\n return formatCollapsedChildrenLine(widget, indentation, ctx.config, collapseReason);\n};\n\nconst formatWidget = (widget: Gtk.Widget, indentation: string, depth: number, ctx: FormatContext): string => {\n const { config } = ctx;\n const tag = getTypeTag(widget);\n const attrs = formatAttrs(buildAttrs(widget, ctx.getId), config.colors);\n const openTag = `${paint(config.colors.tag, \"<\" + tag)}${attrs}${paint(config.colors.tag, \">\")}`;\n const closeTag = paint(config.colors.tag, `</${tag}>`);\n const text = getWidgetText(widget);\n const openLine = `${indentation}${openTag}${config.spacingOuter}`;\n\n if (!text && !widget.getFirstChild()) {\n return openLine;\n }\n\n const textLine = text ? `${indentation}${config.indent}${text}${config.spacingOuter}` : \"\";\n const body = formatBody(widget, indentation, depth, ctx);\n\n return `${openLine}${textLine}${body}${indentation}${closeTag}${config.spacingOuter}`;\n};\n\nconst createWidgetPlugin = (options: PrettyWidgetOptions): NewPlugin => ({\n test: (value: unknown): boolean => value instanceof Gtk.Widget,\n serialize: (widget: Gtk.Widget, config: Config, indentation: string): string =>\n formatWidget(widget, indentation, 0, { getId: options.getId, config, maxDepth: options.maxDepth }),\n});\n\nconst resolveMaxLength = (options: PrettyWidgetOptions): number => {\n const envLimit = process.env.DEBUG_PRINT_LIMIT ? Number(process.env.DEBUG_PRINT_LIMIT) : DEFAULT_MAX_LENGTH;\n\n return options.maxLength ?? envLimit;\n};\n\nconst formatOptions = (options: PrettyWidgetOptions): PrettyFormatOptions => {\n const { plugins, ...rest } = options.prettyFormatOptions ?? {};\n\n return {\n highlight: options.shouldHighlight ?? isHighlightSupported(),\n ...rest,\n plugins: [createWidgetPlugin(options), ...(plugins ?? [])],\n };\n};\n\n/**\n * Renders a widget tree as an indented, HTML-like string showing each widget's\n * tag, accessible attributes, and text content.\n *\n * @param container The scope whose widget tree is formatted.\n * @param options Formatting options such as truncation length and highlighting.\n * @returns The formatted representation of the tree.\n */\nconst prettyWidget = (container: Container, options: PrettyWidgetOptions = {}): string => {\n const maxLength = resolveMaxLength(options);\n\n if (maxLength === 0) {\n return \"\";\n }\n\n const prettyFormatOptions = formatOptions(options);\n let output = \"\";\n\n for (const root of roots(container)) {\n output += format(root, prettyFormatOptions);\n }\n\n if (output.length > maxLength) {\n return `${output.slice(0, maxLength)}...`;\n }\n\n return output.trimEnd();\n};\n\n/**\n * Prints one or more widget trees to the console using {@link prettyWidget}.\n *\n * @param container A single scope or an array of scopes to format and print.\n * @param options Formatting options passed through to {@link prettyWidget}.\n */\nconst logWidget = (container: Container | Container[], options?: PrettyWidgetOptions): void => {\n const containers: Container[] = Array.isArray(container) ? container : [container];\n\n for (const target of containers) {\n console.log(prettyWidget(target, options));\n }\n};\n\nexport { logWidget, prettyWidget, type PrettyWidgetOptions };\n"]}
1
+ {"version":3,"file":"pretty-widget.js","sourceRoot":"","sources":["../src/pretty-widget.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Gtk from \"@gtkx/gi/gtk\";\nimport { sortStringsBy } from \"@gtkx/utils\";\nimport { type Config, format, type NewPlugin, type PrettyFormatOptions } from \"@vitest/pretty-format\";\nimport { formatRole } from \"./role-helpers.js\";\nimport { type Container, descendants, isOnScreen, roots } from \"./traversal.js\";\nimport { getWidgetText } from \"./widget-accessible-properties.js\";\nimport { getTypeTag } from \"./widget-getters.js\";\n\n/** Produces the value of the `id` attribute printed first on a widget's opening tag. */\ntype WidgetIdResolver = (widget: Gtk.Widget) => string;\n\n/**\n * Options controlling how a widget tree is rendered to a string by\n * {@link prettyWidget} and {@link logWidget}.\n */\ntype PrettyWidgetOptions = {\n /** Truncates the output once it exceeds this many characters. */\n maxLength?: number;\n /** Whether to apply ANSI color highlighting; defaults to the terminal capabilities. */\n shouldHighlight?: boolean;\n /** Resolves an `id` attribute to show for each widget. */\n getId?: WidgetIdResolver;\n /** Stops descending past this depth, replacing deeper children with a summary line. */\n maxDepth?: number;\n /** Forwarded to pretty-format, which does the printing; `indent` and `min` shape the layout. */\n prettyFormatOptions?: PrettyFormatOptions;\n};\n\ntype Color = { open: string; close: string };\n\ntype FormatContext = {\n getId: WidgetIdResolver | undefined;\n config: Config;\n maxDepth: number | undefined;\n};\n\nconst DEFAULT_MAX_LENGTH = 7000;\n\nconst buildAttrs = (widget: Gtk.Widget, getId: WidgetIdResolver | undefined): [string, string][] => {\n const attrs: [string, string][] = [];\n\n if (getId) {\n attrs.push([\"id\", getId(widget)]);\n }\n\n const name = widget.getName();\n\n if (name) {\n attrs.push([\"name\", name]);\n }\n\n attrs.push([\"role\", formatRole(widget.getAccessibleRole())]);\n\n if (!widget.getSensitive()) {\n attrs.push([\"accessible-disabled\", \"true\"]);\n }\n\n if (!widget.getVisible()) {\n attrs.push([\"accessible-hidden\", \"true\"]);\n }\n\n if (!isOnScreen(widget)) {\n attrs.push([\"mapped\", \"false\"]);\n }\n\n const idAttrs = attrs.filter(([key]) => key === \"id\");\n\n const otherAttrs = sortStringsBy(\n attrs.filter(([key]) => key !== \"id\"),\n ([key]) => key,\n );\n\n return [...idAttrs, ...otherAttrs];\n};\n\nconst isHighlightSupported = (): boolean => {\n if (process.env.COLORS === \"false\" || process.env.NO_COLOR) {\n return false;\n }\n\n if (process.env.COLORS === \"true\" || process.env.FORCE_COLOR) {\n return true;\n }\n\n return process.stdout.isTTY;\n};\n\nconst paint = (color: Color, text: string): string => `${color.open}${text}${color.close}`;\nconst escapeAttrValue = (value: string): string => value.replaceAll('\"', \"&quot;\");\n\nconst formatAttr = (key: string, value: string, colors: Config[\"colors\"]): string => {\n const quoted = `\"${escapeAttrValue(value)}\"`;\n\n return ` ${paint(colors.prop, key)}=${paint(colors.value, quoted)}`;\n};\n\nconst formatAttrs = (attrs: [string, string][], colors: Config[\"colors\"]): string =>\n attrs.map(([key, value]) => formatAttr(key, value, colors)).join(\"\");\n\nconst countChildren = (widget: Gtk.Widget): number => {\n let count = 0;\n let child = widget.getFirstChild();\n\n while (child) {\n count += 1;\n child = child.getNextSibling();\n }\n\n return count;\n};\n\nconst depthLimitReason = (widget: Gtk.Widget, getId: WidgetIdResolver | undefined): string => {\n const hint = getId ? ` (pass rootId=\"${getId(widget)}\" or raise maxDepth to expand)` : \"\";\n\n return `hidden${hint}`;\n};\n\nconst hasMappedDescendant = (widget: Gtk.Widget): boolean => {\n for (const descendant of descendants(widget)) {\n if (isOnScreen(descendant)) {\n return true;\n }\n }\n\n return false;\n};\n\nconst collapseReasonFor = (widget: Gtk.Widget, depth: number, ctx: FormatContext): string | null => {\n if (!widget.getFirstChild()) {\n return null;\n }\n\n if (!isOnScreen(widget) && !hasMappedDescendant(widget)) {\n return \"not mapped\";\n }\n\n if (ctx.maxDepth !== undefined && depth >= ctx.maxDepth) {\n return depthLimitReason(widget, ctx.getId);\n }\n\n return null;\n};\n\nconst formatCollapsedChildrenLine = (\n widget: Gtk.Widget,\n indentation: string,\n config: Config,\n reason: string,\n): string => {\n const count = countChildren(widget);\n const plural = count === 1 ? \"\" : \"s\";\n const summary = `… ${String(count)} child widget${plural} ${reason}`;\n\n return `${indentation}${config.indent}${paint(config.colors.tag, summary)}${config.spacingOuter}`;\n};\n\nconst formatChildren = (widget: Gtk.Widget, indentation: string, depth: number, ctx: FormatContext): string => {\n let output = \"\";\n let child = widget.getFirstChild();\n\n while (child) {\n output += formatWidget(child, indentation + ctx.config.indent, depth + 1, ctx);\n child = child.getNextSibling();\n }\n\n return output;\n};\n\nconst formatBody = (widget: Gtk.Widget, indentation: string, depth: number, ctx: FormatContext): string => {\n const collapseReason = collapseReasonFor(widget, depth, ctx);\n\n if (collapseReason === null) {\n return formatChildren(widget, indentation, depth, ctx);\n }\n\n return formatCollapsedChildrenLine(widget, indentation, ctx.config, collapseReason);\n};\n\nconst formatWidget = (widget: Gtk.Widget, indentation: string, depth: number, ctx: FormatContext): string => {\n const { config } = ctx;\n const tag = getTypeTag(widget);\n const attrs = formatAttrs(buildAttrs(widget, ctx.getId), config.colors);\n const openTag = `${paint(config.colors.tag, \"<\" + tag)}${attrs}${paint(config.colors.tag, \">\")}`;\n const closeTag = paint(config.colors.tag, `</${tag}>`);\n const text = getWidgetText(widget);\n const openLine = `${indentation}${openTag}${config.spacingOuter}`;\n\n if (!text && !widget.getFirstChild()) {\n return openLine;\n }\n\n const textLine = text ? `${indentation}${config.indent}${text}${config.spacingOuter}` : \"\";\n const body = formatBody(widget, indentation, depth, ctx);\n\n return `${openLine}${textLine}${body}${indentation}${closeTag}${config.spacingOuter}`;\n};\n\nconst createWidgetPlugin = (options: PrettyWidgetOptions): NewPlugin => ({\n test: (value: unknown): boolean => value instanceof Gtk.Widget,\n serialize: (widget: Gtk.Widget, config: Config, indentation: string): string =>\n formatWidget(widget, indentation, 0, { getId: options.getId, config, maxDepth: options.maxDepth }),\n});\n\nconst resolveMaxLength = (options: PrettyWidgetOptions): number => {\n const envLimit = process.env.DEBUG_PRINT_LIMIT ? Number(process.env.DEBUG_PRINT_LIMIT) : DEFAULT_MAX_LENGTH;\n\n return options.maxLength ?? envLimit;\n};\n\nconst formatOptions = (options: PrettyWidgetOptions): PrettyFormatOptions => {\n const { plugins, ...rest } = options.prettyFormatOptions ?? {};\n\n return {\n highlight: options.shouldHighlight ?? isHighlightSupported(),\n ...rest,\n plugins: [createWidgetPlugin(options), ...(plugins ?? [])],\n };\n};\n\n/**\n * Renders a widget tree as an indented, HTML-like string showing each widget's\n * tag, accessible attributes, and text content.\n *\n * @param container The scope whose widget tree is formatted.\n * @param options Formatting options such as truncation length and highlighting.\n * @returns The formatted representation of the tree.\n */\nconst prettyWidget = (container: Container, options: PrettyWidgetOptions = {}): string => {\n const maxLength = resolveMaxLength(options);\n\n if (maxLength === 0) {\n return \"\";\n }\n\n const prettyFormatOptions = formatOptions(options);\n let output = \"\";\n\n for (const root of roots(container)) {\n output += format(root, prettyFormatOptions);\n }\n\n if (output.length > maxLength) {\n return `${output.slice(0, maxLength)}...`;\n }\n\n return output.trimEnd();\n};\n\n/**\n * Prints one or more widget trees to the console using {@link prettyWidget}.\n *\n * @param container A single scope or an array of scopes to format and print.\n * @param options Formatting options passed through to {@link prettyWidget}.\n */\nconst logWidget = (container: Container | Container[], options?: PrettyWidgetOptions): void => {\n const containers: Container[] = Array.isArray(container) ? container : [container];\n\n for (const target of containers) {\n console.log(prettyWidget(target, options));\n }\n};\n\nexport { logWidget, prettyWidget, type PrettyWidgetOptions };\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gtkx/testing",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "Queries, events, and screenshots for GTK and GTK4 widget trees.",
5
5
  "keywords": [
6
6
  "gtkx",
@@ -60,9 +60,9 @@
60
60
  "dependencies": {
61
61
  "@vitest/expect": "^4.1.11",
62
62
  "@vitest/pretty-format": "^4.1.11",
63
- "@gtkx/runtime": "1.4.0",
64
- "@gtkx/react": "1.4.0",
65
- "@gtkx/utils": "1.4.0"
63
+ "@gtkx/react": "1.5.0",
64
+ "@gtkx/runtime": "1.5.0",
65
+ "@gtkx/utils": "1.5.0"
66
66
  },
67
67
  "peerDependencies": {
68
68
  "@types/react": "^19.2",
@@ -70,7 +70,7 @@
70
70
  },
71
71
  "devDependencies": {
72
72
  "@types/react": "^19.2.18",
73
- "@gtkx/config": "1.4.0"
73
+ "@gtkx/config": "1.5.0"
74
74
  },
75
75
  "scripts": {
76
76
  "release": "tsx ../../scripts/release-package.ts"
package/src/act.ts CHANGED
@@ -19,18 +19,10 @@ const actImplementation: ActImplementation = reactAct;
19
19
  */
20
20
  const act: ActImplementation = withGlobalActEnvironment(actImplementation);
21
21
 
22
- const getGlobalThis = (): typeof globalThis => {
23
- if (typeof globalThis !== "undefined") {
24
- return globalThis;
25
- }
26
-
27
- throw new Error("unable to locate global object");
28
- };
29
-
30
- const getIsReactActEnvironment = (): boolean | undefined => getGlobalThis().IS_REACT_ACT_ENVIRONMENT;
22
+ const getIsReactActEnvironment = (): boolean | undefined => globalThis.IS_REACT_ACT_ENVIRONMENT;
31
23
 
32
24
  const setIsReactActEnvironment = (value: boolean | undefined): void => {
33
- getGlobalThis().IS_REACT_ACT_ENVIRONMENT = value;
25
+ Reflect.set(globalThis, "IS_REACT_ACT_ENVIRONMENT", value);
34
26
  };
35
27
 
36
28
  const isThenable = <T>(value: unknown): value is PromiseLike<T> =>
@@ -74,10 +74,6 @@ const buildAttrs = (widget: Gtk.Widget, getId: WidgetIdResolver | undefined): [s
74
74
  };
75
75
 
76
76
  const isHighlightSupported = (): boolean => {
77
- if (typeof process === "undefined") {
78
- return false;
79
- }
80
-
81
77
  if (process.env.COLORS === "false" || process.env.NO_COLOR) {
82
78
  return false;
83
79
  }