@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
|
+
export * as prettyFormat from "@vitest/pretty-format";
|
package/src/pretty-widget.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
2
2
|
import { sortStringsBy } from "@gtkx/utils";
|
|
3
|
+
import { type Config, format, type NewPlugin, type PrettyFormatOptions } from "@vitest/pretty-format";
|
|
3
4
|
import { formatRole } from "./role-helpers.js";
|
|
4
|
-
import { type Container, roots } from "./traversal.js";
|
|
5
|
-
import {
|
|
5
|
+
import { type Container, descendants, isOnScreen, roots } from "./traversal.js";
|
|
6
|
+
import { getWidgetText } from "./widget-accessible-properties.js";
|
|
7
|
+
import { getTypeTag } from "./widget-getters.js";
|
|
6
8
|
|
|
7
9
|
/** Produces the value of the `id` attribute printed first on a widget's opening tag. */
|
|
8
10
|
type WidgetIdResolver = (widget: Gtk.Widget) => string;
|
|
@@ -20,29 +22,19 @@ type PrettyWidgetOptions = {
|
|
|
20
22
|
getId?: WidgetIdResolver;
|
|
21
23
|
/** Stops descending past this depth, replacing deeper children with a summary line. */
|
|
22
24
|
maxDepth?: number;
|
|
25
|
+
/** Forwarded to pretty-format, which does the printing; `indent` and `min` shape the layout. */
|
|
26
|
+
prettyFormatOptions?: PrettyFormatOptions;
|
|
23
27
|
};
|
|
24
28
|
|
|
25
|
-
type
|
|
26
|
-
tag: (s: string) => string;
|
|
27
|
-
attr: (s: string) => string;
|
|
28
|
-
value: (s: string) => string;
|
|
29
|
-
};
|
|
29
|
+
type Color = { open: string; close: string };
|
|
30
30
|
|
|
31
31
|
type FormatContext = {
|
|
32
32
|
getId: WidgetIdResolver | undefined;
|
|
33
|
-
|
|
33
|
+
config: Config;
|
|
34
34
|
maxDepth: number | undefined;
|
|
35
35
|
};
|
|
36
36
|
|
|
37
37
|
const DEFAULT_MAX_LENGTH = 7000;
|
|
38
|
-
const INDENT = " ";
|
|
39
|
-
|
|
40
|
-
const ansi = {
|
|
41
|
-
cyan: "\u{1B}[36m",
|
|
42
|
-
yellow: "\u{1B}[33m",
|
|
43
|
-
green: "\u{1B}[32m",
|
|
44
|
-
reset: "\u{1B}[0m",
|
|
45
|
-
};
|
|
46
38
|
|
|
47
39
|
const buildAttrs = (widget: Gtk.Widget, getId: WidgetIdResolver | undefined): [string, string][] => {
|
|
48
40
|
const attrs: [string, string][] = [];
|
|
@@ -67,6 +59,10 @@ const buildAttrs = (widget: Gtk.Widget, getId: WidgetIdResolver | undefined): [s
|
|
|
67
59
|
attrs.push(["accessible-hidden", "true"]);
|
|
68
60
|
}
|
|
69
61
|
|
|
62
|
+
if (!isOnScreen(widget)) {
|
|
63
|
+
attrs.push(["mapped", "false"]);
|
|
64
|
+
}
|
|
65
|
+
|
|
70
66
|
const idAttrs = attrs.filter(([key]) => key === "id");
|
|
71
67
|
|
|
72
68
|
const otherAttrs = sortStringsBy(
|
|
@@ -93,29 +89,16 @@ const isHighlightSupported = (): boolean => {
|
|
|
93
89
|
return process.stdout.isTTY;
|
|
94
90
|
};
|
|
95
91
|
|
|
96
|
-
const
|
|
97
|
-
if (!isEnabled) {
|
|
98
|
-
const identity = (s: string): string => s;
|
|
99
|
-
|
|
100
|
-
return { tag: identity, attr: identity, value: identity };
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return {
|
|
104
|
-
tag: (s) => `${ansi.cyan}${s}${ansi.reset}`,
|
|
105
|
-
attr: (s) => `${ansi.yellow}${s}${ansi.reset}`,
|
|
106
|
-
value: (s) => `${ansi.green}${s}${ansi.reset}`,
|
|
107
|
-
};
|
|
108
|
-
};
|
|
109
|
-
|
|
92
|
+
const paint = (color: Color, text: string): string => `${color.open}${text}${color.close}`;
|
|
110
93
|
const escapeAttrValue = (value: string): string => value.replaceAll('"', """);
|
|
111
94
|
|
|
112
|
-
const formatAttr = (key: string, value: string, colors:
|
|
95
|
+
const formatAttr = (key: string, value: string, colors: Config["colors"]): string => {
|
|
113
96
|
const quoted = `"${escapeAttrValue(value)}"`;
|
|
114
97
|
|
|
115
|
-
return ` ${colors.
|
|
98
|
+
return ` ${paint(colors.prop, key)}=${paint(colors.value, quoted)}`;
|
|
116
99
|
};
|
|
117
100
|
|
|
118
|
-
const formatAttrs = (attrs: [string, string][], colors:
|
|
101
|
+
const formatAttrs = (attrs: [string, string][], colors: Config["colors"]): string =>
|
|
119
102
|
attrs.map(([key, value]) => formatAttr(key, value, colors)).join("");
|
|
120
103
|
|
|
121
104
|
const countChildren = (widget: Gtk.Widget): number => {
|
|
@@ -130,68 +113,114 @@ const countChildren = (widget: Gtk.Widget): number => {
|
|
|
130
113
|
return count;
|
|
131
114
|
};
|
|
132
115
|
|
|
133
|
-
const
|
|
134
|
-
const { getId, colors } = ctx;
|
|
135
|
-
const indent = INDENT.repeat(depth);
|
|
136
|
-
const count = countChildren(widget);
|
|
116
|
+
const depthLimitReason = (widget: Gtk.Widget, getId: WidgetIdResolver | undefined): string => {
|
|
137
117
|
const hint = getId ? ` (pass rootId="${getId(widget)}" or raise maxDepth to expand)` : "";
|
|
118
|
+
|
|
119
|
+
return `hidden${hint}`;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const hasMappedDescendant = (widget: Gtk.Widget): boolean => {
|
|
123
|
+
for (const descendant of descendants(widget)) {
|
|
124
|
+
if (isOnScreen(descendant)) {
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return false;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const collapseReasonFor = (widget: Gtk.Widget, depth: number, ctx: FormatContext): string | null => {
|
|
133
|
+
if (!widget.getFirstChild()) {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (!isOnScreen(widget) && !hasMappedDescendant(widget)) {
|
|
138
|
+
return "not mapped";
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (ctx.maxDepth !== undefined && depth >= ctx.maxDepth) {
|
|
142
|
+
return depthLimitReason(widget, ctx.getId);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return null;
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const formatCollapsedChildrenLine = (
|
|
149
|
+
widget: Gtk.Widget,
|
|
150
|
+
indentation: string,
|
|
151
|
+
config: Config,
|
|
152
|
+
reason: string,
|
|
153
|
+
): string => {
|
|
154
|
+
const count = countChildren(widget);
|
|
138
155
|
const plural = count === 1 ? "" : "s";
|
|
139
|
-
const summary = `… ${String(count)} child widget${plural}
|
|
156
|
+
const summary = `… ${String(count)} child widget${plural} ${reason}`;
|
|
140
157
|
|
|
141
|
-
return `${
|
|
158
|
+
return `${indentation}${config.indent}${paint(config.colors.tag, summary)}${config.spacingOuter}`;
|
|
142
159
|
};
|
|
143
160
|
|
|
144
|
-
const formatChildren = (widget: Gtk.Widget, depth: number, ctx: FormatContext): string => {
|
|
161
|
+
const formatChildren = (widget: Gtk.Widget, indentation: string, depth: number, ctx: FormatContext): string => {
|
|
145
162
|
let output = "";
|
|
146
163
|
let child = widget.getFirstChild();
|
|
147
164
|
|
|
148
165
|
while (child) {
|
|
149
|
-
output += formatWidget(child, depth + 1, ctx);
|
|
166
|
+
output += formatWidget(child, indentation + ctx.config.indent, depth + 1, ctx);
|
|
150
167
|
child = child.getNextSibling();
|
|
151
168
|
}
|
|
152
169
|
|
|
153
170
|
return output;
|
|
154
171
|
};
|
|
155
172
|
|
|
156
|
-
const
|
|
157
|
-
const
|
|
158
|
-
const indent = INDENT.repeat(depth);
|
|
159
|
-
const tag = widget.constructor.name;
|
|
160
|
-
const attrs = formatAttrs(buildAttrs(widget, getId), colors);
|
|
161
|
-
const openTag = `${colors.tag("<")}${colors.tag(tag)}${attrs}${colors.tag(">")}`;
|
|
162
|
-
const closeTag = `${colors.tag("</")}${colors.tag(tag)}${colors.tag(">")}`;
|
|
163
|
-
const text = getWidgetNodeText(widget);
|
|
164
|
-
const firstChild = widget.getFirstChild();
|
|
165
|
-
|
|
166
|
-
if (!text && !firstChild) {
|
|
167
|
-
return `${indent}${openTag}\n`;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
let output = `${indent}${openTag}\n`;
|
|
173
|
+
const formatBody = (widget: Gtk.Widget, indentation: string, depth: number, ctx: FormatContext): string => {
|
|
174
|
+
const collapseReason = collapseReasonFor(widget, depth, ctx);
|
|
171
175
|
|
|
172
|
-
if (
|
|
173
|
-
|
|
176
|
+
if (collapseReason === null) {
|
|
177
|
+
return formatChildren(widget, indentation, depth, ctx);
|
|
174
178
|
}
|
|
175
179
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
output += `${indent}${closeTag}\n`;
|
|
180
|
+
return formatCollapsedChildrenLine(widget, indentation, ctx.config, collapseReason);
|
|
181
|
+
};
|
|
179
182
|
|
|
180
|
-
|
|
183
|
+
const formatWidget = (widget: Gtk.Widget, indentation: string, depth: number, ctx: FormatContext): string => {
|
|
184
|
+
const { config } = ctx;
|
|
185
|
+
const tag = getTypeTag(widget);
|
|
186
|
+
const attrs = formatAttrs(buildAttrs(widget, ctx.getId), config.colors);
|
|
187
|
+
const openTag = `${paint(config.colors.tag, "<" + tag)}${attrs}${paint(config.colors.tag, ">")}`;
|
|
188
|
+
const closeTag = paint(config.colors.tag, `</${tag}>`);
|
|
189
|
+
const text = getWidgetText(widget);
|
|
190
|
+
const openLine = `${indentation}${openTag}${config.spacingOuter}`;
|
|
191
|
+
|
|
192
|
+
if (!text && !widget.getFirstChild()) {
|
|
193
|
+
return openLine;
|
|
181
194
|
}
|
|
182
195
|
|
|
183
|
-
|
|
184
|
-
|
|
196
|
+
const textLine = text ? `${indentation}${config.indent}${text}${config.spacingOuter}` : "";
|
|
197
|
+
const body = formatBody(widget, indentation, depth, ctx);
|
|
185
198
|
|
|
186
|
-
return
|
|
199
|
+
return `${openLine}${textLine}${body}${indentation}${closeTag}${config.spacingOuter}`;
|
|
187
200
|
};
|
|
188
201
|
|
|
202
|
+
const createWidgetPlugin = (options: PrettyWidgetOptions): NewPlugin => ({
|
|
203
|
+
test: (value: unknown): boolean => value instanceof Gtk.Widget,
|
|
204
|
+
serialize: (widget: Gtk.Widget, config: Config, indentation: string): string =>
|
|
205
|
+
formatWidget(widget, indentation, 0, { getId: options.getId, config, maxDepth: options.maxDepth }),
|
|
206
|
+
});
|
|
207
|
+
|
|
189
208
|
const resolveMaxLength = (options: PrettyWidgetOptions): number => {
|
|
190
209
|
const envLimit = process.env.DEBUG_PRINT_LIMIT ? Number(process.env.DEBUG_PRINT_LIMIT) : DEFAULT_MAX_LENGTH;
|
|
191
210
|
|
|
192
211
|
return options.maxLength ?? envLimit;
|
|
193
212
|
};
|
|
194
213
|
|
|
214
|
+
const formatOptions = (options: PrettyWidgetOptions): PrettyFormatOptions => {
|
|
215
|
+
const { plugins, ...rest } = options.prettyFormatOptions ?? {};
|
|
216
|
+
|
|
217
|
+
return {
|
|
218
|
+
highlight: options.shouldHighlight ?? isHighlightSupported(),
|
|
219
|
+
...rest,
|
|
220
|
+
plugins: [createWidgetPlugin(options), ...(plugins ?? [])],
|
|
221
|
+
};
|
|
222
|
+
};
|
|
223
|
+
|
|
195
224
|
/**
|
|
196
225
|
* Renders a widget tree as an indented, HTML-like string showing each widget's
|
|
197
226
|
* tag, accessible attributes, and text content.
|
|
@@ -207,12 +236,11 @@ const prettyWidget = (container: Container, options: PrettyWidgetOptions = {}):
|
|
|
207
236
|
return "";
|
|
208
237
|
}
|
|
209
238
|
|
|
210
|
-
const
|
|
211
|
-
const colors = createColors(shouldHighlight);
|
|
239
|
+
const prettyFormatOptions = formatOptions(options);
|
|
212
240
|
let output = "";
|
|
213
241
|
|
|
214
242
|
for (const root of roots(container)) {
|
|
215
|
-
output +=
|
|
243
|
+
output += format(root, prettyFormatOptions);
|
|
216
244
|
}
|
|
217
245
|
|
|
218
246
|
if (output.length > maxLength) {
|
|
@@ -236,4 +264,4 @@ const logWidget = (container: Container | Container[], options?: PrettyWidgetOpt
|
|
|
236
264
|
}
|
|
237
265
|
};
|
|
238
266
|
|
|
239
|
-
export {
|
|
267
|
+
export { logWidget, prettyWidget, type PrettyWidgetOptions };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type * as Gtk from "@gtkx/gi/gtk";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
import { createRoot, type Root } from "@gtkx/react";
|
|
4
|
+
import { createHarnessWindow } from "./harness-window.js";
|
|
5
|
+
import { delay } from "./timers.js";
|
|
6
|
+
|
|
7
|
+
type ProductionRenderResult = {
|
|
8
|
+
rerender: (element: ReactNode) => Promise<void>;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
type ActiveRender = {
|
|
12
|
+
root: Root;
|
|
13
|
+
window: Gtk.Window;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const SETTLE_TURNS = 3;
|
|
17
|
+
const activeRenders: Set<ActiveRender> = new Set();
|
|
18
|
+
|
|
19
|
+
const settle = async (): Promise<void> => {
|
|
20
|
+
for (let index = 0; index < SETTLE_TURNS; index++) {
|
|
21
|
+
await delay(0);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const render = async (element: ReactNode): Promise<ProductionRenderResult> => {
|
|
26
|
+
const window = createHarnessWindow();
|
|
27
|
+
const root = createRoot(window);
|
|
28
|
+
activeRenders.add({ root, window });
|
|
29
|
+
root.render(element);
|
|
30
|
+
window.present();
|
|
31
|
+
await settle();
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
rerender: async (next: ReactNode): Promise<void> => {
|
|
35
|
+
root.render(next);
|
|
36
|
+
await settle();
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const cleanup = async (): Promise<void> => {
|
|
42
|
+
for (const active of activeRenders) {
|
|
43
|
+
active.root.unmount();
|
|
44
|
+
active.window.destroy();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
activeRenders.clear();
|
|
48
|
+
await settle();
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export { cleanup, render };
|