@gtkx/testing 1.0.0-rc.1 → 1.0.0-rc.3
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/dist/act.d.ts +6 -6
- package/dist/act.d.ts.map +1 -1
- package/dist/act.js +34 -26
- package/dist/act.js.map +1 -1
- package/dist/bound-queries.d.ts +5 -5
- package/dist/bound-queries.d.ts.map +1 -1
- package/dist/bound-queries.js.map +1 -1
- package/dist/build-queries.d.ts +5 -5
- package/dist/build-queries.d.ts.map +1 -1
- package/dist/build-queries.js +21 -9
- package/dist/build-queries.js.map +1 -1
- package/dist/cleanup-registry.d.ts +4 -3
- package/dist/cleanup-registry.d.ts.map +1 -1
- package/dist/cleanup-registry.js +13 -3
- package/dist/cleanup-registry.js.map +1 -1
- package/dist/config.d.ts +5 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +11 -9
- package/dist/config.js.map +1 -1
- package/dist/editable.d.ts +6 -5
- package/dist/editable.d.ts.map +1 -1
- package/dist/editable.js +7 -5
- package/dist/editable.js.map +1 -1
- package/dist/errors.d.ts +7 -6
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +64 -48
- package/dist/errors.js.map +1 -1
- package/dist/fire-event.d.ts +2 -1
- package/dist/fire-event.d.ts.map +1 -1
- package/dist/fire-event.js +2 -1
- package/dist/fire-event.js.map +1 -1
- package/dist/frame-sync.d.ts +2 -1
- package/dist/frame-sync.d.ts.map +1 -1
- package/dist/frame-sync.js +28 -21
- package/dist/frame-sync.js.map +1 -1
- package/dist/index.d.ts +9 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/matchers.d.ts +99 -35
- package/dist/matchers.d.ts.map +1 -1
- package/dist/matchers.js +314 -63
- package/dist/matchers.js.map +1 -1
- package/dist/normalize.d.ts +10 -0
- package/dist/normalize.d.ts.map +1 -0
- package/dist/normalize.js +20 -0
- package/dist/normalize.js.map +1 -0
- package/dist/pretty-widget.d.ts +6 -4
- package/dist/pretty-widget.d.ts.map +1 -1
- package/dist/pretty-widget.js +64 -24
- package/dist/pretty-widget.js.map +1 -1
- package/dist/queries.d.ts +129 -90
- package/dist/queries.d.ts.map +1 -1
- package/dist/queries.js +235 -164
- package/dist/queries.js.map +1 -1
- package/dist/register-test-hooks.js +2 -1
- package/dist/register-test-hooks.js.map +1 -1
- package/dist/render-hook.d.ts +3 -2
- package/dist/render-hook.d.ts.map +1 -1
- package/dist/render-hook.js +2 -1
- package/dist/render-hook.js.map +1 -1
- package/dist/render.d.ts +3 -2
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +25 -19
- package/dist/render.js.map +1 -1
- package/dist/role-helpers.d.ts +6 -5
- package/dist/role-helpers.d.ts.map +1 -1
- package/dist/role-helpers.js +16 -12
- package/dist/role-helpers.js.map +1 -1
- package/dist/screen.d.ts +4 -3
- package/dist/screen.d.ts.map +1 -1
- package/dist/screen.js +13 -11
- package/dist/screen.js.map +1 -1
- package/dist/screenshot.d.ts +4 -3
- package/dist/screenshot.d.ts.map +1 -1
- package/dist/screenshot.js +43 -36
- package/dist/screenshot.js.map +1 -1
- package/dist/suggestions.d.ts +11 -6
- package/dist/suggestions.d.ts.map +1 -1
- package/dist/suggestions.js +10 -5
- package/dist/suggestions.js.map +1 -1
- package/dist/traversal.d.ts +7 -7
- package/dist/traversal.d.ts.map +1 -1
- package/dist/traversal.js +17 -11
- package/dist/traversal.js.map +1 -1
- package/dist/types.d.ts +65 -24
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/user-event/adjustment.d.ts +5 -3
- package/dist/user-event/adjustment.d.ts.map +1 -1
- package/dist/user-event/adjustment.js +6 -4
- package/dist/user-event/adjustment.js.map +1 -1
- package/dist/user-event/click.d.ts +6 -5
- package/dist/user-event/click.d.ts.map +1 -1
- package/dist/user-event/click.js +29 -21
- package/dist/user-event/click.js.map +1 -1
- package/dist/user-event/controller.d.ts +7 -5
- package/dist/user-event/controller.d.ts.map +1 -1
- package/dist/user-event/controller.js +16 -6
- package/dist/user-event/controller.js.map +1 -1
- package/dist/user-event/dispatch.d.ts +3 -3
- package/dist/user-event/dispatch.d.ts.map +1 -1
- package/dist/user-event/dispatch.js +3 -2
- package/dist/user-event/dispatch.js.map +1 -1
- package/dist/user-event/event-wrapper.d.ts +2 -1
- package/dist/user-event/event-wrapper.d.ts.map +1 -1
- package/dist/user-event/event-wrapper.js +27 -16
- package/dist/user-event/event-wrapper.js.map +1 -1
- package/dist/user-event/gesture.d.ts +18 -14
- package/dist/user-event/gesture.d.ts.map +1 -1
- package/dist/user-event/gesture.js +70 -37
- package/dist/user-event/gesture.js.map +1 -1
- package/dist/user-event/index.d.ts +17 -10
- package/dist/user-event/index.d.ts.map +1 -1
- package/dist/user-event/index.js +7 -3
- package/dist/user-event/index.js.map +1 -1
- package/dist/user-event/keyboard.d.ts +4 -3
- package/dist/user-event/keyboard.d.ts.map +1 -1
- package/dist/user-event/keyboard.js +89 -58
- package/dist/user-event/keyboard.js.map +1 -1
- package/dist/user-event/pointer.d.ts +7 -3
- package/dist/user-event/pointer.d.ts.map +1 -1
- package/dist/user-event/pointer.js +4 -1
- package/dist/user-event/pointer.js.map +1 -1
- package/dist/user-event/selection.d.ts +3 -2
- package/dist/user-event/selection.d.ts.map +1 -1
- package/dist/user-event/selection.js +26 -27
- package/dist/user-event/selection.js.map +1 -1
- package/dist/user-event/state.d.ts +3 -2
- package/dist/user-event/state.d.ts.map +1 -1
- package/dist/user-event/state.js +2 -1
- package/dist/user-event/state.js.map +1 -1
- package/dist/user-event/text.d.ts +8 -7
- package/dist/user-event/text.d.ts.map +1 -1
- package/dist/user-event/text.js +39 -33
- package/dist/user-event/text.js.map +1 -1
- package/dist/wait-for.d.ts +5 -5
- package/dist/wait-for.d.ts.map +1 -1
- package/dist/wait-for.js +45 -30
- package/dist/wait-for.js.map +1 -1
- package/dist/widget-accessible-properties.d.ts +36 -25
- package/dist/widget-accessible-properties.d.ts.map +1 -1
- package/dist/widget-accessible-properties.js +215 -68
- package/dist/widget-accessible-properties.js.map +1 -1
- package/dist/within.d.ts +2 -1
- package/dist/within.d.ts.map +1 -1
- package/dist/within.js +2 -1
- package/dist/within.js.map +1 -1
- package/package.json +11 -9
- package/src/act.ts +44 -35
- package/src/bound-queries.ts +6 -6
- package/src/build-queries.ts +84 -43
- package/src/cleanup-registry.ts +18 -5
- package/src/config.ts +16 -12
- package/src/editable.ts +13 -6
- package/src/errors.ts +106 -45
- package/src/fire-event.ts +3 -1
- package/src/frame-sync.ts +38 -21
- package/src/index.ts +13 -3
- package/src/matchers.ts +568 -114
- package/src/normalize.ts +28 -0
- package/src/pretty-widget.ts +114 -42
- package/src/queries.ts +418 -256
- package/src/register-test-hooks.ts +4 -1
- package/src/render-hook.tsx +10 -4
- package/src/render.tsx +59 -34
- package/src/role-helpers.ts +29 -16
- package/src/screen.ts +17 -12
- package/src/screenshot.ts +61 -38
- package/src/suggestions.ts +29 -10
- package/src/traversal.ts +35 -15
- package/src/types.ts +111 -32
- package/src/user-event/adjustment.ts +23 -10
- package/src/user-event/click.ts +49 -20
- package/src/user-event/controller.ts +41 -7
- package/src/user-event/dispatch.ts +4 -2
- package/src/user-event/event-wrapper.ts +42 -16
- package/src/user-event/gesture.ts +135 -50
- package/src/user-event/index.ts +19 -12
- package/src/user-event/keyboard.ts +147 -61
- package/src/user-event/pointer.ts +20 -8
- package/src/user-event/selection.ts +69 -32
- package/src/user-event/state.ts +4 -2
- package/src/user-event/text.ts +73 -38
- package/src/wait-for.ts +77 -36
- package/src/widget-accessible-properties.ts +385 -79
- package/src/within.ts +8 -5
package/dist/matchers.d.ts
CHANGED
|
@@ -1,55 +1,119 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
1
2
|
/** The expected value for a text matcher: an exact string or a regular expression. */
|
|
2
|
-
|
|
3
|
+
type TextExpectation = string | RegExp;
|
|
4
|
+
/** Options controlling how `toHaveTextContent` normalizes the text it reads. */
|
|
5
|
+
type TextContentOptions = {
|
|
6
|
+
/**
|
|
7
|
+
* When true (the default), trim the text and collapse runs of whitespace into single spaces
|
|
8
|
+
* before comparing. When false, only replace non-breaking spaces with regular ones.
|
|
9
|
+
*/
|
|
10
|
+
normalizeWhitespace?: boolean | undefined;
|
|
11
|
+
};
|
|
12
|
+
/** The expected value for a style class: an exact class name or a regular expression. */
|
|
13
|
+
type ClassExpectation = string | RegExp;
|
|
3
14
|
type MatcherResult = {
|
|
4
15
|
pass: boolean;
|
|
5
16
|
message: () => string;
|
|
6
17
|
};
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
type TextMatcher = (
|
|
11
|
-
type StateMatcher = (
|
|
12
|
-
type
|
|
13
|
-
|
|
14
|
-
export declare const toHaveTextContent: TextMatcher;
|
|
15
|
-
export declare const toHaveAccessibleName: TextMatcher;
|
|
16
|
-
export declare const toHavePlaceholderText: TextMatcher;
|
|
17
|
-
export declare const toBeChecked: StateMatcher;
|
|
18
|
-
export declare const toBePressed: StateMatcher;
|
|
19
|
-
export declare const toBeExpanded: StateMatcher;
|
|
20
|
-
export declare const toBeSelected: StateMatcher;
|
|
21
|
-
export declare const toHaveValue: ValueMatcher;
|
|
22
|
-
interface MatcherImplementations {
|
|
18
|
+
type MatcherContext = {
|
|
19
|
+
equals: (actual: unknown, expected: unknown) => boolean;
|
|
20
|
+
};
|
|
21
|
+
type TextMatcher = (received: unknown, expected?: TextExpectation) => MatcherResult;
|
|
22
|
+
type StateMatcher = (received: unknown) => MatcherResult;
|
|
23
|
+
type TextContentMatcher = (received: unknown, expected?: TextExpectation, options?: TextContentOptions) => MatcherResult;
|
|
24
|
+
type MatcherImplementations = {
|
|
23
25
|
toHaveDisplayValue: TextMatcher;
|
|
24
|
-
toHaveTextContent:
|
|
26
|
+
toHaveTextContent: TextContentMatcher;
|
|
25
27
|
toHaveAccessibleName: TextMatcher;
|
|
28
|
+
toHaveAccessibleDescription: TextMatcher;
|
|
29
|
+
toHaveAccessibleErrorMessage: TextMatcher;
|
|
26
30
|
toHavePlaceholderText: TextMatcher;
|
|
31
|
+
toHaveSelection: TextMatcher;
|
|
27
32
|
toBeChecked: StateMatcher;
|
|
33
|
+
toBePartiallyChecked: StateMatcher;
|
|
28
34
|
toBePressed: StateMatcher;
|
|
29
35
|
toBeExpanded: StateMatcher;
|
|
30
36
|
toBeSelected: StateMatcher;
|
|
31
|
-
|
|
32
|
-
|
|
37
|
+
toBeDisabled: StateMatcher;
|
|
38
|
+
toBeEnabled: StateMatcher;
|
|
39
|
+
toBeVisible: StateMatcher;
|
|
40
|
+
toBeRooted: StateMatcher;
|
|
41
|
+
toBeEmpty: StateMatcher;
|
|
42
|
+
toBeInvalid: StateMatcher;
|
|
43
|
+
toBeValid: StateMatcher;
|
|
44
|
+
toBeRequired: StateMatcher;
|
|
45
|
+
toHaveFocus: StateMatcher;
|
|
46
|
+
toHaveValue: (received: unknown, expected?: number | string) => MatcherResult;
|
|
47
|
+
toHaveRole: (received: unknown, expected: Gtk.AccessibleRole) => MatcherResult;
|
|
48
|
+
toContainElement: (received: unknown, descendant: Gtk.Widget | null) => MatcherResult;
|
|
49
|
+
toHaveClass: (received: unknown, ...args: unknown[]) => MatcherResult;
|
|
50
|
+
toHaveObjectProperty: (this: MatcherContext, received: unknown, ...args: unknown[]) => MatcherResult;
|
|
51
|
+
};
|
|
52
|
+
declare const toHaveAccessibleName: TextMatcher;
|
|
53
|
+
declare const toHaveAccessibleDescription: TextMatcher;
|
|
54
|
+
declare const toHaveAccessibleErrorMessage: TextMatcher;
|
|
55
|
+
declare const toHavePlaceholderText: TextMatcher;
|
|
56
|
+
declare const toHaveSelection: TextMatcher;
|
|
57
|
+
declare const toBePressed: StateMatcher;
|
|
58
|
+
declare const toBeExpanded: StateMatcher;
|
|
59
|
+
declare const toBeSelected: StateMatcher;
|
|
60
|
+
declare const toBeRequired: StateMatcher;
|
|
33
61
|
/** The widget assertion matchers keyed by name, suitable for passing to `expect.extend`. */
|
|
34
|
-
|
|
62
|
+
declare const matchers: MatcherImplementations;
|
|
63
|
+
declare function toHaveTextContent(received: unknown, expected?: TextExpectation, options?: TextContentOptions): MatcherResult;
|
|
64
|
+
declare function toBeChecked(received: unknown): MatcherResult;
|
|
65
|
+
declare function toBePartiallyChecked(received: unknown): MatcherResult;
|
|
66
|
+
declare function toHaveDisplayValue(received: unknown, expected?: TextExpectation): MatcherResult;
|
|
67
|
+
declare function toHaveValue(received: unknown, expected?: number | string): MatcherResult;
|
|
68
|
+
declare function toBeDisabled(received: unknown): MatcherResult;
|
|
69
|
+
declare function toBeEnabled(received: unknown): MatcherResult;
|
|
70
|
+
declare function toBeVisible(received: unknown): MatcherResult;
|
|
71
|
+
declare function toBeRooted(received: unknown): MatcherResult;
|
|
72
|
+
declare function toBeEmpty(received: unknown): MatcherResult;
|
|
73
|
+
declare function toBeInvalid(received: unknown): MatcherResult;
|
|
74
|
+
declare function toBeValid(received: unknown): MatcherResult;
|
|
75
|
+
declare function toHaveFocus(received: unknown): MatcherResult;
|
|
76
|
+
declare function toHaveRole(received: unknown, expected: Gtk.AccessibleRole): MatcherResult;
|
|
77
|
+
declare function toContainElement(received: unknown, descendant: Gtk.Widget | null): MatcherResult;
|
|
78
|
+
declare function toHaveClass(received: unknown, ...args: unknown[]): MatcherResult;
|
|
79
|
+
declare function toHaveObjectProperty(this: MatcherContext, received: unknown, ...args: unknown[]): MatcherResult;
|
|
35
80
|
/** Registers the widget matchers on the global `expect`, when one is available. Safe to call more than once. */
|
|
36
|
-
|
|
37
|
-
interface WidgetMatchers<R = void> {
|
|
38
|
-
toHaveDisplayValue(expected?: TextExpectation): R;
|
|
39
|
-
toHaveTextContent(expected?: TextExpectation): R;
|
|
40
|
-
toHaveAccessibleName(expected?: TextExpectation): R;
|
|
41
|
-
toHavePlaceholderText(expected?: TextExpectation): R;
|
|
42
|
-
toBeChecked(): R;
|
|
43
|
-
toBePressed(): R;
|
|
44
|
-
toBeExpanded(): R;
|
|
45
|
-
toBeSelected(): R;
|
|
46
|
-
toHaveValue(expected: number): R;
|
|
47
|
-
}
|
|
81
|
+
declare const registerMatchers: () => void;
|
|
48
82
|
declare module "@vitest/expect" {
|
|
49
|
-
interface
|
|
83
|
+
interface WidgetMatchers {
|
|
84
|
+
toHaveDisplayValue(expected?: TextExpectation): void;
|
|
85
|
+
toHaveTextContent(expected?: TextExpectation, options?: TextContentOptions): void;
|
|
86
|
+
toHaveAccessibleName(expected?: TextExpectation): void;
|
|
87
|
+
toHaveAccessibleDescription(expected?: TextExpectation): void;
|
|
88
|
+
toHaveAccessibleErrorMessage(expected?: TextExpectation): void;
|
|
89
|
+
toHavePlaceholderText(expected?: TextExpectation): void;
|
|
90
|
+
toHaveSelection(expected?: TextExpectation): void;
|
|
91
|
+
toBeChecked(): void;
|
|
92
|
+
toBePartiallyChecked(): void;
|
|
93
|
+
toBePressed(): void;
|
|
94
|
+
toBeExpanded(): void;
|
|
95
|
+
toBeSelected(): void;
|
|
96
|
+
toBeDisabled(): void;
|
|
97
|
+
toBeEnabled(): void;
|
|
98
|
+
toBeVisible(): void;
|
|
99
|
+
toBeRooted(): void;
|
|
100
|
+
toBeEmpty(): void;
|
|
101
|
+
toBeInvalid(): void;
|
|
102
|
+
toBeValid(): void;
|
|
103
|
+
toBeRequired(): void;
|
|
104
|
+
toHaveFocus(): void;
|
|
105
|
+
toHaveValue(expected?: number | string): void;
|
|
106
|
+
toHaveRole(expected: Gtk.AccessibleRole): void;
|
|
107
|
+
toContainElement(descendant: Gtk.Widget | null): void;
|
|
108
|
+
toHaveClass(...args: (ClassExpectation | {
|
|
109
|
+
exact: boolean;
|
|
110
|
+
})[]): void;
|
|
111
|
+
toHaveObjectProperty(name: string, expected?: unknown): void;
|
|
112
|
+
}
|
|
113
|
+
interface Assertion extends WidgetMatchers {
|
|
50
114
|
}
|
|
51
115
|
interface AsymmetricMatchersContaining extends WidgetMatchers {
|
|
52
116
|
}
|
|
53
117
|
}
|
|
54
|
-
export {};
|
|
118
|
+
export { toHaveDisplayValue, toHaveTextContent, toHaveAccessibleName, toHaveAccessibleDescription, toHaveAccessibleErrorMessage, toHavePlaceholderText, toHaveSelection, toBeChecked, toBePartiallyChecked, toBePressed, toBeExpanded, toBeSelected, toBeDisabled, toBeEnabled, toBeVisible, toBeRooted, toBeEmpty, toBeInvalid, toBeValid, toBeRequired, toHaveFocus, toHaveValue, toHaveRole, toContainElement, toHaveClass, toHaveObjectProperty, matchers, registerMatchers, type ClassExpectation, type TextContentOptions, type TextExpectation, };
|
|
55
119
|
//# sourceMappingURL=matchers.d.ts.map
|
package/dist/matchers.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matchers.d.ts","sourceRoot":"","sources":["../src/matchers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"matchers.d.ts","sourceRoot":"","sources":["../src/matchers.ts"],"names":[],"mappings":"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"}
|
package/dist/matchers.js
CHANGED
|
@@ -1,18 +1,68 @@
|
|
|
1
1
|
/// <reference types="@vitest/expect" />
|
|
2
|
+
import * as GObject from "@gtkx/gi/gobject";
|
|
2
3
|
import * as Gtk from "@gtkx/gi/gtk";
|
|
3
|
-
import {
|
|
4
|
+
import { getDefaultNormalizer } from "./normalize.js";
|
|
5
|
+
import { formatRole } from "./role-helpers.js";
|
|
6
|
+
import { getWidgetAccessibleName, getWidgetCheckedState, getWidgetDescribedByText, getWidgetDisplayValue, getWidgetErrorMessage, getWidgetExpandedState, getWidgetInvalidState, getWidgetLabelText, getWidgetPlaceholderText, getWidgetPressedState, getWidgetRequiredState, getWidgetSelectedState, getWidgetSelection, getWidgetTextContent, getWidgetValue, hasDisplayValue, isWidgetDisabled, isWidgetVisible, } from "./widget-accessible-properties.js";
|
|
7
|
+
const registration = { isRegistered: false };
|
|
8
|
+
const displayValueMatcher = textMatcher("toHaveDisplayValue", getWidgetDisplayValue, "exact");
|
|
9
|
+
const toHaveAccessibleName = textMatcher("toHaveAccessibleName", getWidgetAccessibleName, "exact");
|
|
10
|
+
const toHaveAccessibleDescription = textMatcher("toHaveAccessibleDescription", getWidgetDescribedByText, "exact");
|
|
11
|
+
const toHaveAccessibleErrorMessage = textMatcher("toHaveAccessibleErrorMessage", readErrorMessageText, "exact");
|
|
12
|
+
const toHavePlaceholderText = textMatcher("toHavePlaceholderText", getWidgetPlaceholderText, "exact");
|
|
13
|
+
const toHaveSelection = textMatcher("toHaveSelection", getWidgetSelection, "exact");
|
|
14
|
+
const toBePressed = booleanStateMatcher("toBePressed", "pressed", getWidgetPressedState);
|
|
15
|
+
const toBeExpanded = booleanStateMatcher("toBeExpanded", "expanded", getWidgetExpandedState);
|
|
16
|
+
const toBeSelected = booleanStateMatcher("toBeSelected", "selected", getWidgetSelectedState);
|
|
17
|
+
const toBeRequired = booleanStateMatcher("toBeRequired", "required", getWidgetRequiredState);
|
|
18
|
+
/** The widget assertion matchers keyed by name, suitable for passing to `expect.extend`. */
|
|
19
|
+
const matchers = {
|
|
20
|
+
toHaveDisplayValue,
|
|
21
|
+
toHaveTextContent,
|
|
22
|
+
toHaveAccessibleName,
|
|
23
|
+
toHaveAccessibleDescription,
|
|
24
|
+
toHaveAccessibleErrorMessage,
|
|
25
|
+
toHavePlaceholderText,
|
|
26
|
+
toHaveSelection,
|
|
27
|
+
toBeChecked,
|
|
28
|
+
toBePartiallyChecked,
|
|
29
|
+
toBePressed,
|
|
30
|
+
toBeExpanded,
|
|
31
|
+
toBeSelected,
|
|
32
|
+
toBeDisabled,
|
|
33
|
+
toBeEnabled,
|
|
34
|
+
toBeVisible,
|
|
35
|
+
toBeRooted,
|
|
36
|
+
toBeEmpty,
|
|
37
|
+
toBeInvalid,
|
|
38
|
+
toBeValid,
|
|
39
|
+
toBeRequired,
|
|
40
|
+
toHaveFocus,
|
|
41
|
+
toHaveValue,
|
|
42
|
+
toHaveRole,
|
|
43
|
+
toContainElement,
|
|
44
|
+
toHaveClass,
|
|
45
|
+
toHaveObjectProperty,
|
|
46
|
+
};
|
|
4
47
|
const asWidget = (received, matcherName) => {
|
|
5
48
|
if (!(received instanceof Gtk.Widget)) {
|
|
6
49
|
throw new TypeError(`${matcherName}: received value must be a Gtk.Widget, got ${typeof received}`);
|
|
7
50
|
}
|
|
8
51
|
return received;
|
|
9
52
|
};
|
|
53
|
+
const asObject = (received, matcherName) => {
|
|
54
|
+
if (!(received instanceof GObject.Object)) {
|
|
55
|
+
throw new TypeError(`${matcherName}: received value must be a GObject, got ${typeof received}`);
|
|
56
|
+
}
|
|
57
|
+
return received;
|
|
58
|
+
};
|
|
10
59
|
const describeWidget = (widget) => {
|
|
11
60
|
const role = Gtk.AccessibleRole[widget.getAccessibleRole()];
|
|
12
61
|
const name = getWidgetAccessibleName(widget);
|
|
13
|
-
return name
|
|
62
|
+
return name === null ? `<${role}>` : `<${role} name=${JSON.stringify(name)}>`;
|
|
14
63
|
};
|
|
15
|
-
const
|
|
64
|
+
const describeObject = (object) => object instanceof Gtk.Widget ? describeWidget(object) : `<${object.constructor.name}>`;
|
|
65
|
+
const isTextMatch = (actual, expected, mode) => {
|
|
16
66
|
if (expected instanceof RegExp) {
|
|
17
67
|
expected.lastIndex = 0;
|
|
18
68
|
return expected.test(actual);
|
|
@@ -20,67 +70,45 @@ const matchesText = (actual, expected, mode) => {
|
|
|
20
70
|
return mode === "exact" ? actual === expected : actual.includes(expected);
|
|
21
71
|
};
|
|
22
72
|
const describeExpected = (expected) => expected instanceof RegExp ? String(expected) : JSON.stringify(expected);
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
if (expected === undefined) {
|
|
27
|
-
const pass = actual !== null && actual !== "";
|
|
28
|
-
return {
|
|
29
|
-
pass,
|
|
30
|
-
message: () => `expected widget ${this.isNot ? "not " : ""}to have a non-empty value for ${matcherName}, ` +
|
|
31
|
-
`but got ${JSON.stringify(actual)}\n${describeWidget(widget)}`,
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
const pass = actual !== null && matchesText(actual, expected, mode);
|
|
73
|
+
const negationPrefix = (isPass) => (isPass ? "not " : "");
|
|
74
|
+
const nonEmptyResult = ({ matcherName, widget, actual }) => {
|
|
75
|
+
const isPass = actual !== null && actual !== "";
|
|
35
76
|
return {
|
|
36
|
-
pass,
|
|
37
|
-
message: () => `expected widget ${
|
|
38
|
-
`but
|
|
77
|
+
pass: isPass,
|
|
78
|
+
message: () => `expected widget ${negationPrefix(isPass)}to have a non-empty value for ${matcherName}, ` +
|
|
79
|
+
`but got ${JSON.stringify(actual)}\n${describeWidget(widget)}`,
|
|
39
80
|
};
|
|
40
81
|
};
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
82
|
+
const matchedResult = (context, expected, isPass) => ({
|
|
83
|
+
pass: isPass,
|
|
84
|
+
message: () => `expected widget ${negationPrefix(isPass)}${context.matcherName} ${describeExpected(expected)}, ` +
|
|
85
|
+
`but received ${JSON.stringify(context.actual)}\n${describeWidget(context.widget)}`,
|
|
86
|
+
});
|
|
87
|
+
const stateResult = (widget, stateName, isPass) => ({
|
|
88
|
+
pass: isPass,
|
|
89
|
+
message: () => `expected widget ${negationPrefix(isPass)}to be ${stateName}\n${describeWidget(widget)}`,
|
|
90
|
+
});
|
|
91
|
+
const camelCase = (name) => name.replaceAll(/-([a-z])/g, (_match, letter) => letter.toUpperCase());
|
|
92
|
+
const isAsymmetricMatcher = (value) => typeof value === "object" && value !== null && typeof Reflect.get(value, "asymmetricMatch") === "function";
|
|
93
|
+
const isEqualValue = (context, actual, expected) => {
|
|
94
|
+
if (isAsymmetricMatcher(expected)) {
|
|
95
|
+
return context.equals(actual, expected);
|
|
47
96
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
message: () => `expected widget ${this.isNot ? "not " : ""}to be ${stateName}\n${describeWidget(widget)}`,
|
|
51
|
-
};
|
|
52
|
-
};
|
|
53
|
-
export const toHaveDisplayValue = textMatcher("toHaveDisplayValue", getWidgetDisplayValue, "exact");
|
|
54
|
-
export const toHaveTextContent = textMatcher("toHaveTextContent", (widget) => getWidgetNodeText(widget) ?? getWidgetAccessibleName(widget), "substring");
|
|
55
|
-
export const toHaveAccessibleName = textMatcher("toHaveAccessibleName", getWidgetAccessibleName, "exact");
|
|
56
|
-
export const toHavePlaceholderText = textMatcher("toHavePlaceholderText", getWidgetPlaceholderText, "exact");
|
|
57
|
-
export const toBeChecked = booleanStateMatcher("toBeChecked", "checked", getWidgetCheckedState);
|
|
58
|
-
export const toBePressed = booleanStateMatcher("toBePressed", "pressed", getWidgetPressedState);
|
|
59
|
-
export const toBeExpanded = booleanStateMatcher("toBeExpanded", "expanded", getWidgetExpandedState);
|
|
60
|
-
export const toBeSelected = booleanStateMatcher("toBeSelected", "selected", getWidgetSelectedState);
|
|
61
|
-
export const toHaveValue = function (received, expected) {
|
|
62
|
-
const widget = asWidget(received, "toHaveValue");
|
|
63
|
-
const actual = getWidgetValue(widget).now;
|
|
64
|
-
if (actual === null) {
|
|
65
|
-
throw new Error(`toHaveValue: widget does not expose a numeric value ` +
|
|
66
|
-
`(role ${Gtk.AccessibleRole[widget.getAccessibleRole()]})\n${describeWidget(widget)}`);
|
|
97
|
+
if (actual instanceof GObject.Object || expected instanceof GObject.Object) {
|
|
98
|
+
return Object.is(actual, expected);
|
|
67
99
|
}
|
|
68
|
-
return
|
|
69
|
-
pass: actual === expected,
|
|
70
|
-
message: () => `expected widget ${this.isNot ? "not " : ""}to have value ${expected}, but received ${actual}\n${describeWidget(widget)}`,
|
|
71
|
-
};
|
|
100
|
+
return context.equals(actual, expected);
|
|
72
101
|
};
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
toHaveValue,
|
|
102
|
+
const isClassMatch = (actual, expected) => expected instanceof RegExp ? actual.some((name) => expected.test(name)) : actual.includes(expected);
|
|
103
|
+
const isWidgetRooted = (widget) => {
|
|
104
|
+
const root = widget.getRoot();
|
|
105
|
+
if (root === null) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
if (root instanceof Gtk.Window) {
|
|
109
|
+
return Gtk.Window.listToplevels().includes(root);
|
|
110
|
+
}
|
|
111
|
+
return true;
|
|
84
112
|
};
|
|
85
113
|
const globalExpect = () => {
|
|
86
114
|
const candidate = Reflect.get(globalThis, "expect");
|
|
@@ -89,15 +117,238 @@ const globalExpect = () => {
|
|
|
89
117
|
}
|
|
90
118
|
return null;
|
|
91
119
|
};
|
|
92
|
-
|
|
120
|
+
function readErrorMessageText(widget) {
|
|
121
|
+
const state = getWidgetInvalidState(widget);
|
|
122
|
+
if (state === null || state === Gtk.AccessibleInvalidState.FALSE) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
const targets = getWidgetErrorMessage(widget);
|
|
126
|
+
if (targets === null) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
const texts = targets.map((target) => getWidgetAccessibleName(target)).filter((text) => text !== null);
|
|
130
|
+
return texts.length > 0 ? texts.join(" ") : null;
|
|
131
|
+
}
|
|
132
|
+
function assertReadableProperty(object, name, property, value) {
|
|
133
|
+
if (typeof value === "function") {
|
|
134
|
+
throw new TypeError(`toHaveObjectProperty: "${name}" is shadowed by a method of the same name; ` +
|
|
135
|
+
`call ${property}() and assert on its result instead`);
|
|
136
|
+
}
|
|
137
|
+
if (value === undefined && !Reflect.has(object, property)) {
|
|
138
|
+
throw new TypeError(`toHaveObjectProperty: no readable property "${name}" on ${describeObject(object)}; ` +
|
|
139
|
+
"construct-only and write-only properties cannot be read back");
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function readObjectProperty(object, name) {
|
|
143
|
+
const property = camelCase(name);
|
|
144
|
+
const value = Reflect.get(object, property);
|
|
145
|
+
assertReadableProperty(object, name, property, value);
|
|
146
|
+
return value;
|
|
147
|
+
}
|
|
148
|
+
function classEntries(entry) {
|
|
149
|
+
return entry instanceof RegExp ? [entry] : String(entry).split(/\s+/).filter(Boolean);
|
|
150
|
+
}
|
|
151
|
+
function parseClassArguments(args) {
|
|
152
|
+
const last = args.at(-1);
|
|
153
|
+
const isOptions = typeof last === "object" && last !== null && !(last instanceof RegExp);
|
|
154
|
+
const isExact = isOptions && Reflect.get(last, "exact") === true;
|
|
155
|
+
const entries = isOptions ? args.slice(0, -1) : args;
|
|
156
|
+
return { expected: entries.flatMap((entry) => classEntries(entry)), isExact };
|
|
157
|
+
}
|
|
158
|
+
function exactClassResult(widget, actual, expected) {
|
|
159
|
+
if (expected.some((entry) => entry instanceof RegExp)) {
|
|
160
|
+
throw new TypeError("toHaveClass: the exact option cannot be combined with a regular expression");
|
|
161
|
+
}
|
|
162
|
+
const names = expected.map(String);
|
|
163
|
+
const isPass = names.length === actual.length && names.every((name) => actual.includes(name));
|
|
164
|
+
return {
|
|
165
|
+
pass: isPass,
|
|
166
|
+
message: () => `expected widget ${negationPrefix(isPass)}to have exactly the classes ${JSON.stringify(names)}, ` +
|
|
167
|
+
`but received ${JSON.stringify(actual)}\n${describeWidget(widget)}`,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
function textMatcher(matcherName, read, mode) {
|
|
171
|
+
return (received, expected) => {
|
|
172
|
+
const widget = asWidget(received, matcherName);
|
|
173
|
+
const actual = read(widget);
|
|
174
|
+
const context = { matcherName, widget, actual };
|
|
175
|
+
if (expected === undefined) {
|
|
176
|
+
return nonEmptyResult(context);
|
|
177
|
+
}
|
|
178
|
+
return matchedResult(context, expected, actual !== null && isTextMatch(actual, expected, mode));
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
function normalizeTextContent(text, options) {
|
|
182
|
+
if (options?.normalizeWhitespace === false) {
|
|
183
|
+
return text.replaceAll("\u{A0}", " ");
|
|
184
|
+
}
|
|
185
|
+
return getDefaultNormalizer()(text);
|
|
186
|
+
}
|
|
187
|
+
function readTextContent(widget, options) {
|
|
188
|
+
const text = getWidgetTextContent(widget);
|
|
189
|
+
return text === null ? null : normalizeTextContent(text, options);
|
|
190
|
+
}
|
|
191
|
+
function toHaveTextContent(received, expected, options) {
|
|
192
|
+
const read = (widget) => readTextContent(widget, options);
|
|
193
|
+
return textMatcher("toHaveTextContent", read, "substring")(received, expected);
|
|
194
|
+
}
|
|
195
|
+
function notApplicable(matcherName, stateName, widget) {
|
|
196
|
+
return new Error(`${matcherName}: widget does not expose a ${stateName} ` +
|
|
197
|
+
`(role ${Gtk.AccessibleRole[widget.getAccessibleRole()]})\n${describeWidget(widget)}`);
|
|
198
|
+
}
|
|
199
|
+
function booleanStateMatcher(matcherName, stateName, read) {
|
|
200
|
+
return (received) => {
|
|
201
|
+
const widget = asWidget(received, matcherName);
|
|
202
|
+
const state = read(widget);
|
|
203
|
+
if (state === null) {
|
|
204
|
+
throw notApplicable(matcherName, `${stateName} state`, widget);
|
|
205
|
+
}
|
|
206
|
+
return stateResult(widget, stateName, state);
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
function readCheckedState(widget, matcherName) {
|
|
210
|
+
const state = getWidgetCheckedState(widget);
|
|
211
|
+
if (state === null) {
|
|
212
|
+
throw notApplicable(matcherName, "checked state", widget);
|
|
213
|
+
}
|
|
214
|
+
return state;
|
|
215
|
+
}
|
|
216
|
+
function toBeChecked(received) {
|
|
217
|
+
const widget = asWidget(received, "toBeChecked");
|
|
218
|
+
return stateResult(widget, "checked", readCheckedState(widget, "toBeChecked") === "checked");
|
|
219
|
+
}
|
|
220
|
+
function toBePartiallyChecked(received) {
|
|
221
|
+
const widget = asWidget(received, "toBePartiallyChecked");
|
|
222
|
+
return stateResult(widget, "partially checked", readCheckedState(widget, "toBePartiallyChecked") === "mixed");
|
|
223
|
+
}
|
|
224
|
+
function toHaveDisplayValue(received, expected) {
|
|
225
|
+
const widget = asWidget(received, "toHaveDisplayValue");
|
|
226
|
+
if (!hasDisplayValue(widget)) {
|
|
227
|
+
throw notApplicable("toHaveDisplayValue", "display value", widget);
|
|
228
|
+
}
|
|
229
|
+
return displayValueMatcher(received, expected);
|
|
230
|
+
}
|
|
231
|
+
function toHaveValue(received, expected) {
|
|
232
|
+
const widget = asWidget(received, "toHaveValue");
|
|
233
|
+
if (typeof expected === "string") {
|
|
234
|
+
return displayValueMatcher(received, expected);
|
|
235
|
+
}
|
|
236
|
+
const actual = getWidgetValue(widget).now;
|
|
237
|
+
if (actual === null) {
|
|
238
|
+
throw notApplicable("toHaveValue", "numeric value", widget);
|
|
239
|
+
}
|
|
240
|
+
const isPass = expected === undefined || actual === expected;
|
|
241
|
+
return {
|
|
242
|
+
pass: isPass,
|
|
243
|
+
message: () => `expected widget ${negationPrefix(isPass)}to have value ${String(expected)}, ` +
|
|
244
|
+
`but received ${String(actual)}\n${describeWidget(widget)}`,
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
function toBeDisabled(received) {
|
|
248
|
+
const widget = asWidget(received, "toBeDisabled");
|
|
249
|
+
return stateResult(widget, "disabled", isWidgetDisabled(widget));
|
|
250
|
+
}
|
|
251
|
+
function toBeEnabled(received) {
|
|
252
|
+
const widget = asWidget(received, "toBeEnabled");
|
|
253
|
+
return stateResult(widget, "enabled", !isWidgetDisabled(widget));
|
|
254
|
+
}
|
|
255
|
+
function toBeVisible(received) {
|
|
256
|
+
const widget = asWidget(received, "toBeVisible");
|
|
257
|
+
return stateResult(widget, "visible", isWidgetVisible(widget));
|
|
258
|
+
}
|
|
259
|
+
function toBeRooted(received) {
|
|
260
|
+
if (received === null) {
|
|
261
|
+
return { pass: false, message: () => "expected a widget to be rooted in a window, but received null" };
|
|
262
|
+
}
|
|
263
|
+
const widget = asWidget(received, "toBeRooted");
|
|
264
|
+
return stateResult(widget, "rooted in a window", isWidgetRooted(widget));
|
|
265
|
+
}
|
|
266
|
+
function toBeEmpty(received) {
|
|
267
|
+
const widget = asWidget(received, "toBeEmpty");
|
|
268
|
+
return stateResult(widget, "empty", widget.getFirstChild() === null && getWidgetLabelText(widget) === null);
|
|
269
|
+
}
|
|
270
|
+
function toBeInvalid(received) {
|
|
271
|
+
const widget = asWidget(received, "toBeInvalid");
|
|
272
|
+
const state = getWidgetInvalidState(widget);
|
|
273
|
+
return stateResult(widget, "invalid", state !== null && state !== Gtk.AccessibleInvalidState.FALSE);
|
|
274
|
+
}
|
|
275
|
+
function toBeValid(received) {
|
|
276
|
+
const widget = asWidget(received, "toBeValid");
|
|
277
|
+
const state = getWidgetInvalidState(widget);
|
|
278
|
+
return stateResult(widget, "valid", state === null || state === Gtk.AccessibleInvalidState.FALSE);
|
|
279
|
+
}
|
|
280
|
+
function toHaveFocus(received) {
|
|
281
|
+
const widget = asWidget(received, "toHaveFocus");
|
|
282
|
+
return stateResult(widget, "focused", widget.getPlatformState(Gtk.AccessiblePlatformState.FOCUSED));
|
|
283
|
+
}
|
|
284
|
+
function toHaveRole(received, expected) {
|
|
285
|
+
const widget = asWidget(received, "toHaveRole");
|
|
286
|
+
const actual = widget.getAccessibleRole();
|
|
287
|
+
const isPass = actual === expected;
|
|
288
|
+
return {
|
|
289
|
+
pass: isPass,
|
|
290
|
+
message: () => `expected widget ${negationPrefix(isPass)}to have role '${formatRole(expected)}', ` +
|
|
291
|
+
`but received '${formatRole(actual)}'\n${describeWidget(widget)}`,
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
function toContainElement(received, descendant) {
|
|
295
|
+
const widget = asWidget(received, "toContainElement");
|
|
296
|
+
const isPass = descendant !== null && (descendant === widget || descendant.isAncestor(widget));
|
|
297
|
+
return {
|
|
298
|
+
pass: isPass,
|
|
299
|
+
message: () => `expected widget ${negationPrefix(isPass)}to contain ` +
|
|
300
|
+
`${descendant === null ? "null" : describeWidget(descendant)}\n${describeWidget(widget)}`,
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
function toHaveClass(received, ...args) {
|
|
304
|
+
const widget = asWidget(received, "toHaveClass");
|
|
305
|
+
const actual = widget.getCssClasses();
|
|
306
|
+
const { expected, isExact } = parseClassArguments(args);
|
|
307
|
+
if (isExact) {
|
|
308
|
+
return exactClassResult(widget, actual, expected);
|
|
309
|
+
}
|
|
310
|
+
if (expected.length === 0) {
|
|
311
|
+
return stateResult(widget, "given any style class", actual.length > 0);
|
|
312
|
+
}
|
|
313
|
+
const isPass = expected.every((entry) => isClassMatch(actual, entry));
|
|
314
|
+
return {
|
|
315
|
+
pass: isPass,
|
|
316
|
+
message: () => `expected widget ${negationPrefix(isPass)}to have class ${expected.map(String).join(", ")}, ` +
|
|
317
|
+
`but received ${JSON.stringify(actual)}\n${describeWidget(widget)}`,
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
function toHaveObjectProperty(received, ...args) {
|
|
321
|
+
const object = asObject(received, "toHaveObjectProperty");
|
|
322
|
+
const [name, expected] = args;
|
|
323
|
+
const actual = readObjectProperty(object, String(name));
|
|
324
|
+
if (args.length < 2) {
|
|
325
|
+
const isSet = actual !== null && actual !== undefined;
|
|
326
|
+
return {
|
|
327
|
+
pass: isSet,
|
|
328
|
+
message: () => `expected ${describeObject(object)} ${negationPrefix(isSet)}to have a value for property ` +
|
|
329
|
+
`"${String(name)}", but received ${JSON.stringify(actual)}`,
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
/* eslint-disable-next-line unicorn/no-this-outside-of-class --
|
|
333
|
+
expect.extend invokes matchers with the matcher state as `this` */
|
|
334
|
+
const isPass = isEqualValue(this, actual, expected);
|
|
335
|
+
return {
|
|
336
|
+
pass: isPass,
|
|
337
|
+
message: () => `expected ${describeObject(object)} ${negationPrefix(isPass)}to have property "${String(name)}" ` +
|
|
338
|
+
`equal to ${JSON.stringify(expected)}, but received ${JSON.stringify(actual)}`,
|
|
339
|
+
};
|
|
340
|
+
}
|
|
93
341
|
/** Registers the widget matchers on the global `expect`, when one is available. Safe to call more than once. */
|
|
94
|
-
|
|
95
|
-
if (
|
|
342
|
+
const registerMatchers = () => {
|
|
343
|
+
if (registration.isRegistered) {
|
|
96
344
|
return;
|
|
345
|
+
}
|
|
97
346
|
const expect = globalExpect();
|
|
98
|
-
if (!expect)
|
|
347
|
+
if (!expect) {
|
|
99
348
|
return;
|
|
349
|
+
}
|
|
100
350
|
expect.extend(matchers);
|
|
101
|
-
|
|
351
|
+
registration.isRegistered = true;
|
|
102
352
|
};
|
|
353
|
+
export { toHaveDisplayValue, toHaveTextContent, toHaveAccessibleName, toHaveAccessibleDescription, toHaveAccessibleErrorMessage, toHavePlaceholderText, toHaveSelection, toBeChecked, toBePartiallyChecked, toBePressed, toBeExpanded, toBeSelected, toBeDisabled, toBeEnabled, toBeVisible, toBeRooted, toBeEmpty, toBeInvalid, toBeValid, toBeRequired, toHaveFocus, toHaveValue, toHaveRole, toContainElement, toHaveClass, toHaveObjectProperty, matchers, registerMatchers, };
|
|
103
354
|
//# sourceMappingURL=matchers.js.map
|