@dynatrace/strato-components-testing 3.11.2 → 3.12.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.
Files changed (130) hide show
  1. package/esm/jest/index.js +9 -1
  2. package/esm/jest/index.js.map +2 -2
  3. package/esm/jest/mocks/create-range-mock.js +4 -22
  4. package/esm/jest/mocks/create-range-mock.js.map +2 -2
  5. package/esm/jest/mocks/fetch-mock.js +4 -14
  6. package/esm/jest/mocks/fetch-mock.js.map +2 -2
  7. package/esm/jest/mocks/framer-motion-mock.js +3 -48
  8. package/esm/jest/mocks/framer-motion-mock.js.map +3 -3
  9. package/esm/jest/mocks/intersection-observer-mock.js +4 -35
  10. package/esm/jest/mocks/intersection-observer-mock.js.map +2 -2
  11. package/esm/jest/mocks/match-media-mock.js +4 -21
  12. package/esm/jest/mocks/match-media-mock.js.map +2 -2
  13. package/esm/jest/mocks/resize-observer-mock.js +4 -18
  14. package/esm/jest/mocks/resize-observer-mock.js.map +2 -2
  15. package/esm/jest/mocks/scroll-into-view-mock.js +4 -10
  16. package/esm/jest/mocks/scroll-into-view-mock.js.map +2 -2
  17. package/esm/jest/testing-helpers/filters/filter-field.js +12 -415
  18. package/esm/jest/testing-helpers/filters/filter-field.js.map +2 -2
  19. package/esm/jest/testing-helpers/tables/datatable.js +1 -11
  20. package/esm/jest/testing-helpers/tables/datatable.js.map +2 -2
  21. package/esm/jest/testing-helpers/utils/setup-user-event.js +1 -1
  22. package/esm/jest/testing-helpers/utils/setup-user-event.js.map +2 -2
  23. package/esm/shared/mocks/create-range-mock.js +29 -0
  24. package/esm/shared/mocks/create-range-mock.js.map +7 -0
  25. package/esm/shared/mocks/fetch-mock.js +23 -0
  26. package/esm/shared/mocks/fetch-mock.js.map +7 -0
  27. package/esm/shared/mocks/framer-motion-mock.js +54 -0
  28. package/esm/shared/mocks/framer-motion-mock.js.map +7 -0
  29. package/esm/shared/mocks/intersection-observer-mock.js +39 -0
  30. package/esm/shared/mocks/intersection-observer-mock.js.map +7 -0
  31. package/esm/shared/mocks/match-media-mock.js +28 -0
  32. package/esm/shared/mocks/match-media-mock.js.map +7 -0
  33. package/esm/shared/mocks/resize-observer-mock.js +25 -0
  34. package/esm/shared/mocks/resize-observer-mock.js.map +7 -0
  35. package/esm/shared/mocks/scroll-into-view-mock.js +17 -0
  36. package/esm/shared/mocks/scroll-into-view-mock.js.map +7 -0
  37. package/esm/shared/testing-helpers/filters/filter-field.js +439 -0
  38. package/esm/shared/testing-helpers/filters/filter-field.js.map +7 -0
  39. package/esm/vitest/index.js +149 -0
  40. package/esm/vitest/index.js.map +7 -0
  41. package/esm/vitest/mocks/create-range-mock.js +10 -0
  42. package/esm/vitest/mocks/create-range-mock.js.map +7 -0
  43. package/esm/vitest/mocks/fetch-mock.js +10 -0
  44. package/esm/vitest/mocks/fetch-mock.js.map +7 -0
  45. package/esm/vitest/mocks/framer-motion-mock.js +13 -0
  46. package/esm/vitest/mocks/framer-motion-mock.js.map +7 -0
  47. package/esm/vitest/mocks/intersection-observer-mock.js +10 -0
  48. package/esm/vitest/mocks/intersection-observer-mock.js.map +7 -0
  49. package/esm/vitest/mocks/match-media-mock.js +10 -0
  50. package/esm/vitest/mocks/match-media-mock.js.map +7 -0
  51. package/esm/vitest/mocks/resize-observer-mock.js +10 -0
  52. package/esm/vitest/mocks/resize-observer-mock.js.map +7 -0
  53. package/esm/vitest/mocks/scroll-into-view-mock.js +10 -0
  54. package/esm/vitest/mocks/scroll-into-view-mock.js.map +7 -0
  55. package/esm/vitest/preset/index.js +5 -0
  56. package/esm/vitest/preset/index.js.map +7 -0
  57. package/esm/vitest/preset/vitest-preset.js +9 -0
  58. package/esm/vitest/preset/vitest-preset.js.map +7 -0
  59. package/esm/vitest/setup/index.js +77 -0
  60. package/esm/vitest/setup/index.js.map +7 -0
  61. package/esm/vitest/testing-helpers/filters/filter-field.js +24 -0
  62. package/esm/vitest/testing-helpers/filters/filter-field.js.map +7 -0
  63. package/esm/vitest/testing-helpers/utils/isFakeTimersEnabled.js +8 -0
  64. package/esm/vitest/testing-helpers/utils/isFakeTimersEnabled.js.map +7 -0
  65. package/esm/vitest/testing-helpers/utils/setup-user-event.js +16 -0
  66. package/esm/vitest/testing-helpers/utils/setup-user-event.js.map +7 -0
  67. package/jest/index.d.ts +3 -1
  68. package/jest/index.js +4 -0
  69. package/jest/mocks/create-range-mock.d.ts +4 -11
  70. package/jest/mocks/create-range-mock.js +4 -22
  71. package/jest/mocks/fetch-mock.d.ts +4 -10
  72. package/jest/mocks/fetch-mock.js +4 -14
  73. package/jest/mocks/framer-motion-mock.js +3 -46
  74. package/jest/mocks/intersection-observer-mock.d.ts +4 -11
  75. package/jest/mocks/intersection-observer-mock.js +4 -35
  76. package/jest/mocks/match-media-mock.d.ts +4 -11
  77. package/jest/mocks/match-media-mock.js +4 -21
  78. package/jest/mocks/resize-observer-mock.d.ts +4 -13
  79. package/jest/mocks/resize-observer-mock.js +4 -18
  80. package/jest/mocks/scroll-into-view-mock.d.ts +4 -10
  81. package/jest/mocks/scroll-into-view-mock.js +4 -10
  82. package/jest/testing-helpers/filters/filter-field.d.ts +5 -109
  83. package/jest/testing-helpers/filters/filter-field.js +11 -414
  84. package/jest/testing-helpers/tables/datatable.js +1 -11
  85. package/jest/testing-helpers/utils/setup-user-event.js +1 -1
  86. package/package.json +3 -3
  87. package/shared/mocks/create-range-mock.d.ts +7 -0
  88. package/shared/mocks/create-range-mock.js +47 -0
  89. package/shared/mocks/fetch-mock.d.ts +13 -0
  90. package/shared/mocks/fetch-mock.js +41 -0
  91. package/shared/mocks/framer-motion-mock.d.ts +15 -0
  92. package/shared/mocks/framer-motion-mock.js +70 -0
  93. package/shared/mocks/intersection-observer-mock.d.ts +7 -0
  94. package/shared/mocks/intersection-observer-mock.js +57 -0
  95. package/shared/mocks/match-media-mock.d.ts +7 -0
  96. package/shared/mocks/match-media-mock.js +46 -0
  97. package/shared/mocks/resize-observer-mock.d.ts +8 -0
  98. package/shared/mocks/resize-observer-mock.js +43 -0
  99. package/shared/mocks/scroll-into-view-mock.d.ts +7 -0
  100. package/shared/mocks/scroll-into-view-mock.js +35 -0
  101. package/shared/testing-helpers/filters/filter-field.d.ts +128 -0
  102. package/shared/testing-helpers/filters/filter-field.js +449 -0
  103. package/vitest/index.d.ts +32 -0
  104. package/vitest/index.js +98 -0
  105. package/vitest/mocks/create-range-mock.d.ts +5 -0
  106. package/vitest/mocks/create-range-mock.js +28 -0
  107. package/vitest/mocks/fetch-mock.d.ts +5 -0
  108. package/vitest/mocks/fetch-mock.js +28 -0
  109. package/vitest/mocks/framer-motion-mock.d.ts +27 -0
  110. package/vitest/mocks/framer-motion-mock.js +31 -0
  111. package/vitest/mocks/intersection-observer-mock.d.ts +5 -0
  112. package/vitest/mocks/intersection-observer-mock.js +28 -0
  113. package/vitest/mocks/match-media-mock.d.ts +5 -0
  114. package/vitest/mocks/match-media-mock.js +28 -0
  115. package/vitest/mocks/resize-observer-mock.d.ts +5 -0
  116. package/vitest/mocks/resize-observer-mock.js +28 -0
  117. package/vitest/mocks/scroll-into-view-mock.d.ts +5 -0
  118. package/vitest/mocks/scroll-into-view-mock.js +28 -0
  119. package/vitest/preset/index.d.ts +2 -0
  120. package/vitest/preset/index.js +23 -0
  121. package/vitest/preset/vitest-preset.d.ts +24 -0
  122. package/vitest/preset/vitest-preset.js +27 -0
  123. package/vitest/setup/index.d.ts +2 -0
  124. package/vitest/setup/index.js +40 -0
  125. package/vitest/testing-helpers/filters/filter-field.d.ts +6 -0
  126. package/vitest/testing-helpers/filters/filter-field.js +36 -0
  127. package/vitest/testing-helpers/utils/isFakeTimersEnabled.d.ts +6 -0
  128. package/vitest/testing-helpers/utils/isFakeTimersEnabled.js +26 -0
  129. package/vitest/testing-helpers/utils/setup-user-event.d.ts +7 -0
  130. package/vitest/testing-helpers/utils/setup-user-event.js +44 -0
@@ -1,14 +1,5 @@
1
- import { PartialDeep } from 'type-fest';
2
- /**
3
- * Mocks the Resize Observer
4
- * @public
5
- */
6
- export declare function setupResizeObserverMock(
7
- /** When the Resize Observer should return specific results, you can pass them here */
8
- mockedObserveCallbackValue?: PartialDeep<ResizeObserverEntry>[]): void;
9
- /**
10
- * Clears the Resize Observer
11
- * @public
12
- */
13
- export declare function clearResizeObserverMock(): void;
1
+ /** @public */
2
+ export declare const setupResizeObserverMock: (mockedObserveCallbackValue?: import("type-fest").PartialDeep<ResizeObserverEntry>[]) => void;
3
+ /** @public */
4
+ export declare const clearResizeObserverMock: () => void;
14
5
  //# sourceMappingURL=resize-observer-mock.d.ts.map
@@ -22,21 +22,7 @@ __export(resize_observer_mock_exports, {
22
22
  });
23
23
  module.exports = __toCommonJS(resize_observer_mock_exports);
24
24
  var import_globals = require("@jest/globals");
25
- const pristineResizeObserver = window.ResizeObserver;
26
- function setupResizeObserverMock(mockedObserveCallbackValue) {
27
- Object.defineProperty(window, "ResizeObserver", {
28
- writable: true,
29
- value: import_globals.jest.fn(
30
- (callback) => ({
31
- observe: mockedObserveCallbackValue ? import_globals.jest.fn().mockImplementation(() => {
32
- callback(mockedObserveCallbackValue);
33
- }) : import_globals.jest.fn(),
34
- unobserve: import_globals.jest.fn(),
35
- disconnect: import_globals.jest.fn()
36
- })
37
- )
38
- });
39
- }
40
- function clearResizeObserverMock() {
41
- window.ResizeObserver = pristineResizeObserver;
42
- }
25
+ var import_resize_observer_mock = require("../../shared/mocks/resize-observer-mock.js");
26
+ const _helpers = (0, import_resize_observer_mock.createResizeObserverMockHelpers)(import_globals.jest.fn);
27
+ const setupResizeObserverMock = _helpers.setupResizeObserverMock;
28
+ const clearResizeObserverMock = _helpers.clearResizeObserverMock;
@@ -1,11 +1,5 @@
1
- /**
2
- * Mocks the scrollIntoView function since jsdom doesn't provide it
3
- * @public
4
- */
5
- export declare function setupScrollIntoViewMock(): void;
6
- /**
7
- * Clears the scrollIntoView
8
- * @public
9
- */
10
- export declare function clearScrollIntoViewMock(): void;
1
+ /** @public */
2
+ export declare const setupScrollIntoViewMock: () => void;
3
+ /** @public */
4
+ export declare const clearScrollIntoViewMock: () => void;
11
5
  //# sourceMappingURL=scroll-into-view-mock.d.ts.map
@@ -22,13 +22,7 @@ __export(scroll_into_view_mock_exports, {
22
22
  });
23
23
  module.exports = __toCommonJS(scroll_into_view_mock_exports);
24
24
  var import_globals = require("@jest/globals");
25
- const pristineScrollIntoView = window.HTMLElement.prototype.scrollIntoView;
26
- function setupScrollIntoViewMock() {
27
- Object.defineProperty(HTMLElement.prototype, "scrollIntoView", {
28
- writable: true,
29
- value: import_globals.jest.fn()
30
- });
31
- }
32
- function clearScrollIntoViewMock() {
33
- window.HTMLElement.prototype.scrollIntoView = pristineScrollIntoView;
34
- }
25
+ var import_scroll_into_view_mock = require("../../shared/mocks/scroll-into-view-mock.js");
26
+ const _helpers = (0, import_scroll_into_view_mock.createScrollIntoViewMockHelpers)(import_globals.jest.fn);
27
+ const setupScrollIntoViewMock = _helpers.setupScrollIntoViewMock;
28
+ const clearScrollIntoViewMock = _helpers.clearScrollIntoViewMock;
@@ -1,110 +1,6 @@
1
- /**
2
- * Base class for pinned or recent filter field suggestion.
3
- * @public */
4
- export declare class FilterFieldPinnedAndRecentSuggestionBase {
5
- protected readonly suggestionRoot: HTMLDivElement;
6
- constructor(suggestionRoot: HTMLDivElement);
7
- private get pinButtonElement();
8
- /**
9
- * Receives the value of the suggestion that would be applied.
10
- */
11
- get value(): string | null;
12
- /**
13
- * Returns if the current suggestion is currently pinned or not.
14
- */
15
- get pinned(): boolean;
16
- /**
17
- * Applies the suggestion to the filter field.
18
- */
19
- apply(): Promise<void>;
20
- get pinEnabled(): boolean;
21
- /**
22
- * Allows the suggestion to be pinned if not pinned already.
23
- */
24
- pin(): Promise<void>;
25
- /**
26
- * Allows the suggestion to be unpinned if not unpinned already.
27
- */
28
- unpin(): Promise<void>;
29
- }
30
- /**
31
- * Testing helper class for pinned suggestions in the filter field
32
- * @public */
33
- export declare class FilterFieldPinnedSuggestion extends FilterFieldPinnedAndRecentSuggestionBase {
34
- /**
35
- * Receives the value of the suggestion that would be applied.
36
- */
37
- get value(): string | null;
38
- }
39
- /**
40
- * Testing helper class for recent suggestions in the filter field
41
- * @public */
42
- export declare class FilterFieldRecentSuggestion extends FilterFieldPinnedAndRecentSuggestionBase {
43
- /**
44
- * Receives the value of the suggestion that would be applied.
45
- */
46
- get value(): string | null;
47
- /**
48
- * Receives time offset indicating when the filter statement has last been used.
49
- */
50
- get lastUsed(): string | null;
51
- }
52
- /**
53
- * Helper class for interacting with the filter field.
54
- * @public
55
- */
56
- export declare class FilterFieldHelper {
57
- private dataTestId;
58
- private get filterFieldWrapper();
59
- private get editorView();
60
- private get inputElement();
61
- private get filterFieldElement();
62
- private get placeholderElement();
63
- private get suggestionsContainer();
64
- constructor(dataTestId: string);
65
- /** Returns the value of the native text input. */
66
- get value(): string;
67
- /** Returns the value of the filter field. */
68
- get filterFieldValue(): string;
69
- /**
70
- * The placeholder text shown in the filter field.
71
- * Undefined if the placeholder is currently not rendered.
72
- */
73
- get placeholder(): string | undefined;
74
- /** Focus the filter field if not already focused. */
75
- focus(): Promise<void>;
76
- /** Blur the filter field by tabbing out of it. */
77
- blur(): Promise<void>;
78
- /** Fill a provided value into the filter field. */
79
- type(text: string, cursorIndex?: number): Promise<void>;
80
- /** Clears the filter field value. */
81
- clear(): Promise<void>;
82
- /**
83
- * Moves the cursor to the given index.
84
- * -1 moves to the end of the input.
85
- */
86
- moveCursorTo(index: number): Promise<void>;
87
- /** Open the suggestions overlay with the keyboard shortcut. */
88
- openSuggestions(): Promise<void>;
89
- /**
90
- * Close the suggestions overlay using the `Escape` key.
91
- * If the filter field is focused, the focus will stay in the filter field.
92
- */
93
- closeSuggestions(): Promise<void>;
94
- /** Apply the suggestion with the given text. */
95
- applySuggestion(queryString: string): Promise<void>;
96
- /** Get recent suggestions */
97
- getRecentSuggestions(): Promise<FilterFieldRecentSuggestion[]>;
98
- /** Get pinned suggestions */
99
- getPinnedSuggestions(): Promise<FilterFieldPinnedSuggestion[]>;
100
- /** Paste text at the current cursor position */
101
- paste(text: string, cursorIndex?: number): Promise<void>;
102
- }
103
- /**
104
- * Helper function that returns the filter field with its testing utilities.
105
- * @public
106
- */
107
- export declare function getFilterFieldHelper(
108
- /** The accessible test id used to locate the filter field wrapper. */
109
- dataTestId: string): FilterFieldHelper;
1
+ import { _FilterFieldDeps, FilterFieldHelper, FilterFieldPinnedAndRecentSuggestionBase, FilterFieldPinnedSuggestion, FilterFieldRecentSuggestion } from '../../../shared/testing-helpers/filters/filter-field.js';
2
+ /** @public */
3
+ export declare const getFilterFieldHelper: (dataTestId: string) => FilterFieldHelper;
4
+ export type { _FilterFieldDeps };
5
+ export { FilterFieldHelper, FilterFieldPinnedAndRecentSuggestionBase, FilterFieldPinnedSuggestion, FilterFieldRecentSuggestion, };
110
6
  //# sourceMappingURL=filter-field.d.ts.map
@@ -17,422 +17,19 @@ var __copyProps = (to, from, except, desc) => {
17
17
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
18
  var filter_field_exports = {};
19
19
  __export(filter_field_exports, {
20
- FilterFieldHelper: () => FilterFieldHelper,
21
- FilterFieldPinnedAndRecentSuggestionBase: () => FilterFieldPinnedAndRecentSuggestionBase,
22
- FilterFieldPinnedSuggestion: () => FilterFieldPinnedSuggestion,
23
- FilterFieldRecentSuggestion: () => FilterFieldRecentSuggestion,
20
+ FilterFieldHelper: () => import_filter_field.FilterFieldHelper,
21
+ FilterFieldPinnedAndRecentSuggestionBase: () => import_filter_field.FilterFieldPinnedAndRecentSuggestionBase,
22
+ FilterFieldPinnedSuggestion: () => import_filter_field.FilterFieldPinnedSuggestion,
23
+ FilterFieldRecentSuggestion: () => import_filter_field.FilterFieldRecentSuggestion,
24
24
  getFilterFieldHelper: () => getFilterFieldHelper
25
25
  });
26
26
  module.exports = __toCommonJS(filter_field_exports);
27
- var import_react = require("@testing-library/react");
28
- var import_user_event = require("@testing-library/user-event");
27
+ var import_filter_field = require("../../../shared/testing-helpers/filters/filter-field.js");
29
28
  var import_isFakeTimersEnabled = require("../utils/isFakeTimersEnabled.js");
30
29
  var import_setup_user_event = require("../utils/setup-user-event.js");
31
- class FilterFieldPinnedAndRecentSuggestionBase {
32
- constructor(suggestionRoot) {
33
- this.suggestionRoot = suggestionRoot;
34
- }
35
- suggestionRoot;
36
- get pinButtonElement() {
37
- return this.suggestionRoot.querySelector(
38
- "button[aria-checked]"
39
- );
40
- }
41
- /**
42
- * Receives the value of the suggestion that would be applied.
43
- */
44
- get value() {
45
- return this.suggestionRoot.childNodes.item(1).textContent;
46
- }
47
- /**
48
- * Returns if the current suggestion is currently pinned or not.
49
- */
50
- get pinned() {
51
- if (this.pinButtonElement) {
52
- return this.pinButtonElement.getAttribute("aria-checked") === "true";
53
- }
54
- return false;
55
- }
56
- /**
57
- * Applies the suggestion to the filter field.
58
- */
59
- async apply() {
60
- await (0, import_setup_user_event.setupUserEvent)({
61
- pointerEventsCheck: import_user_event.PointerEventsCheckLevel.Never
62
- }).click(this.suggestionRoot);
63
- }
64
- get pinEnabled() {
65
- if (this.pinButtonElement) {
66
- return this.pinButtonElement.getAttribute("aria-disabled") === "false";
67
- }
68
- return false;
69
- }
70
- /**
71
- * Allows the suggestion to be pinned if not pinned already.
72
- */
73
- async pin() {
74
- if (this.pinned === true) {
75
- return;
76
- }
77
- if (this.pinButtonElement) {
78
- await (0, import_setup_user_event.setupUserEvent)({
79
- pointerEventsCheck: import_user_event.PointerEventsCheckLevel.Never
80
- }).click(this.pinButtonElement);
81
- if ((0, import_isFakeTimersEnabled.isFakeTimersEnabled)()) {
82
- await (0, import_react.act)(async () => {
83
- jest.runOnlyPendingTimers();
84
- });
85
- }
86
- }
87
- }
88
- /**
89
- * Allows the suggestion to be unpinned if not unpinned already.
90
- */
91
- async unpin() {
92
- if (this.pinned === false) {
93
- return;
94
- }
95
- if (this.pinButtonElement) {
96
- await (0, import_setup_user_event.setupUserEvent)({
97
- pointerEventsCheck: import_user_event.PointerEventsCheckLevel.Never
98
- }).click(this.pinButtonElement);
99
- if ((0, import_isFakeTimersEnabled.isFakeTimersEnabled)()) {
100
- await (0, import_react.act)(async () => {
101
- jest.runOnlyPendingTimers();
102
- });
103
- }
104
- }
105
- }
106
- }
107
- class FilterFieldPinnedSuggestion extends FilterFieldPinnedAndRecentSuggestionBase {
108
- /**
109
- * Receives the value of the suggestion that would be applied.
110
- */
111
- get value() {
112
- return this.suggestionRoot.childNodes.item(0).textContent;
113
- }
114
- }
115
- class FilterFieldRecentSuggestion extends FilterFieldPinnedAndRecentSuggestionBase {
116
- /**
117
- * Receives the value of the suggestion that would be applied.
118
- */
119
- get value() {
120
- return this.suggestionRoot.querySelector('[role="option"]')?.childNodes.item(0).textContent ?? null;
121
- }
122
- /**
123
- * Receives time offset indicating when the filter statement has last been used.
124
- */
125
- get lastUsed() {
126
- return this.suggestionRoot.querySelector('[role="option"]')?.childNodes.item(1).textContent ?? null;
127
- }
128
- }
129
- class FilterFieldHelper {
130
- constructor(dataTestId) {
131
- this.dataTestId = dataTestId;
132
- }
133
- dataTestId;
134
- get filterFieldWrapper() {
135
- return import_react.screen.getByTestId(this.dataTestId);
136
- }
137
- get editorView() {
138
- return this.filterFieldWrapper.querySelector(
139
- ".cm-content"
140
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
141
- )?.cmTile.view;
142
- }
143
- get inputElement() {
144
- return (0, import_react.within)(this.filterFieldWrapper).getAllByRole(
145
- "textbox",
146
- { hidden: true }
147
- )[1];
148
- }
149
- get filterFieldElement() {
150
- return (0, import_react.within)(this.filterFieldWrapper).getByRole(
151
- "textbox",
152
- {
153
- name: "Filter field",
154
- hidden: true
155
- }
156
- );
157
- }
158
- get placeholderElement() {
159
- return this.filterFieldWrapper.querySelector(".cm-placeholder");
160
- }
161
- get suggestionsContainer() {
162
- return import_react.screen.queryByTestId(`filterfield-suggestions-${this.dataTestId}`);
163
- }
164
- /** Returns the value of the native text input. */
165
- get value() {
166
- return this.inputElement.value;
167
- }
168
- /** Returns the value of the filter field. */
169
- get filterFieldValue() {
170
- return this.filterFieldElement.textContent || "";
171
- }
172
- /**
173
- * The placeholder text shown in the filter field.
174
- * Undefined if the placeholder is currently not rendered.
175
- */
176
- get placeholder() {
177
- return this.placeholderElement?.textContent || void 0;
178
- }
179
- /** Focus the filter field if not already focused. */
180
- async focus() {
181
- if (!this.filterFieldWrapper.contains(document.activeElement)) {
182
- await (0, import_react.act)(async () => {
183
- this.inputElement.focus();
184
- });
185
- expect(
186
- this.filterFieldWrapper.contains(document.activeElement)
187
- ).toBeTruthy();
188
- if ((0, import_isFakeTimersEnabled.isFakeTimersEnabled)()) {
189
- await (0, import_react.act)(async () => {
190
- jest.runOnlyPendingTimers();
191
- });
192
- }
193
- }
194
- }
195
- /** Blur the filter field by tabbing out of it. */
196
- async blur() {
197
- await (0, import_react.act)(async () => {
198
- this.filterFieldElement.blur();
199
- });
200
- if ((0, import_isFakeTimersEnabled.isFakeTimersEnabled)()) {
201
- await (0, import_react.act)(async () => {
202
- jest.runOnlyPendingTimers();
203
- });
204
- }
205
- }
206
- /** Fill a provided value into the filter field. */
207
- async type(text, cursorIndex) {
208
- const regEx = new RegExp(text, "g");
209
- const matches = this.value.match(regEx);
210
- await this.moveCursorTo(cursorIndex ?? -1);
211
- await (0, import_setup_user_event.setupUserEvent)({
212
- pointerEventsCheck: import_user_event.PointerEventsCheckLevel.Never
213
- }).keyboard(text);
214
- await (0, import_react.waitFor)(() => {
215
- expect(this.value.match(regEx) ?? []).toHaveLength(
216
- (matches?.length ?? 0) + 1
217
- );
218
- });
219
- if ((0, import_isFakeTimersEnabled.isFakeTimersEnabled)()) {
220
- await (0, import_react.act)(async () => {
221
- jest.runOnlyPendingTimers();
222
- });
223
- }
224
- }
225
- /** Clears the filter field value. */
226
- async clear() {
227
- if (this.value !== "") {
228
- await (0, import_setup_user_event.setupUserEvent)({
229
- pointerEventsCheck: import_user_event.PointerEventsCheckLevel.Never
230
- }).click(
231
- await (0, import_react.within)(this.filterFieldWrapper).findByRole("button", {
232
- name: "Clear filter",
233
- hidden: true
234
- })
235
- );
236
- if ((0, import_isFakeTimersEnabled.isFakeTimersEnabled)()) {
237
- await (0, import_react.act)(async () => {
238
- jest.runOnlyPendingTimers();
239
- });
240
- }
241
- }
242
- }
243
- /**
244
- * Moves the cursor to the given index.
245
- * -1 moves to the end of the input.
246
- */
247
- async moveCursorTo(index) {
248
- const user = (0, import_setup_user_event.setupUserEvent)({
249
- pointerEventsCheck: import_user_event.PointerEventsCheckLevel.Never
250
- });
251
- if (index === -1) {
252
- await (0, import_react.act)(async () => {
253
- await this.focus();
254
- });
255
- await user.keyboard("{PageDown}");
256
- return;
257
- }
258
- if (!this.editorView) {
259
- console.warn("FilterField editor could not be found. Panic now.");
260
- return;
261
- }
262
- await (0, import_react.act)(async () => {
263
- await this.focus();
264
- this.editorView.dispatch({
265
- selection: {
266
- anchor: Math.min(index, this.editorView.state.doc.length)
267
- }
268
- });
269
- });
270
- if ((0, import_isFakeTimersEnabled.isFakeTimersEnabled)()) {
271
- await (0, import_react.act)(async () => {
272
- jest.runOnlyPendingTimers();
273
- });
274
- }
275
- }
276
- /** Open the suggestions overlay with the keyboard shortcut. */
277
- async openSuggestions() {
278
- await (0, import_react.act)(async () => {
279
- await this.focus();
280
- });
281
- await (0, import_setup_user_event.setupUserEvent)({
282
- pointerEventsCheck: import_user_event.PointerEventsCheckLevel.Never
283
- }).keyboard("{Control>}{Space}{/Control}");
284
- await (0, import_react.waitFor)(
285
- async () => expect(this.suggestionsContainer).toBeInTheDocument()
286
- );
287
- if ((0, import_isFakeTimersEnabled.isFakeTimersEnabled)()) {
288
- await (0, import_react.act)(async () => {
289
- jest.runOnlyPendingTimers();
290
- });
291
- }
292
- }
293
- /**
294
- * Close the suggestions overlay using the `Escape` key.
295
- * If the filter field is focused, the focus will stay in the filter field.
296
- */
297
- async closeSuggestions() {
298
- await (0, import_react.act)(async () => {
299
- await this.focus();
300
- });
301
- await (0, import_setup_user_event.setupUserEvent)({
302
- pointerEventsCheck: import_user_event.PointerEventsCheckLevel.Never
303
- }).keyboard("{Escape}");
304
- if (this.suggestionsContainer !== null) {
305
- await (0, import_react.waitForElementToBeRemoved)(() => this.suggestionsContainer);
306
- }
307
- }
308
- /** Apply the suggestion with the given text. */
309
- async applySuggestion(queryString) {
310
- await (0, import_react.act)(async () => {
311
- await this.focus();
312
- });
313
- await (0, import_react.waitFor)(() => {
314
- expect(this.suggestionsContainer).toBeInTheDocument();
315
- });
316
- if (!this.suggestionsContainer) {
317
- console.warn(
318
- "The filter field suggestions overlay seems to be closed. Make sure to open it before applying a suggestion."
319
- );
320
- return;
321
- }
322
- const showMore = (0, import_react.within)(this.suggestionsContainer).queryByRole("option", {
323
- name: "Show more"
324
- });
325
- if (showMore) {
326
- await (0, import_setup_user_event.setupUserEvent)({
327
- pointerEventsCheck: import_user_event.PointerEventsCheckLevel.Never
328
- }).click(showMore);
329
- }
330
- let suggestions = (0, import_react.within)(this.suggestionsContainer).queryAllByTestId(
331
- queryString,
332
- { exact: true }
333
- );
334
- if (suggestions.length > 0) {
335
- suggestions = suggestions.reduce((acc, container) => {
336
- const suggestion = (0, import_react.within)(container).queryByRole("option");
337
- if (suggestion) {
338
- acc.push(suggestion);
339
- }
340
- return acc;
341
- }, []);
342
- }
343
- if (suggestions.length === 0) {
344
- suggestions.push(
345
- ...(0, import_react.within)(this.suggestionsContainer).queryAllByText(
346
- (_, element) => element?.getAttribute("role") === "option" && // The replace is needed to ignore non-breaking spaces
347
- element.firstElementChild?.textContent?.replace(/\s+/g, " ") === queryString.replace(/\s+/g, " ")
348
- )
349
- );
350
- }
351
- if (suggestions.length === 0) {
352
- console.warn(
353
- `Could not query a suggestion with the given queryString '${queryString}' (trying queryByTestId and queryByText).`
354
- );
355
- return;
356
- }
357
- if (suggestions.length > 1) {
358
- console.warn(
359
- "Found multiple suggestions with the given testId. Will apply the first one"
360
- );
361
- }
362
- await (0, import_setup_user_event.setupUserEvent)({
363
- pointerEventsCheck: import_user_event.PointerEventsCheckLevel.Never
364
- }).click(suggestions[0]);
365
- }
366
- /** Get recent suggestions */
367
- async getRecentSuggestions() {
368
- if (this.suggestionsContainer) {
369
- const recentGroup = (0, import_react.within)(this.suggestionsContainer).getByRole("group", {
370
- name: "Recently used filters"
371
- });
372
- const suggestions = (0, import_react.within)(recentGroup).getAllByRole(
373
- "group",
374
- {
375
- hidden: true,
376
- name(_accessibleName, element) {
377
- return element.getAttribute(
378
- "data-strato-filter-field-virtual-focus-type"
379
- ) === "recent-suggestion";
380
- }
381
- }
382
- );
383
- return suggestions.map((el) => new FilterFieldRecentSuggestion(el));
384
- }
385
- return [];
386
- }
387
- /** Get pinned suggestions */
388
- async getPinnedSuggestions() {
389
- if (this.suggestionsContainer) {
390
- try {
391
- await (0, import_react.waitFor)(
392
- () => import_react.screen.getByRole("group", {
393
- name: "Pinned filters",
394
- hidden: true,
395
- suggest: false
396
- })
397
- );
398
- const pinnedGroup = (0, import_react.within)(this.suggestionsContainer).getByRole(
399
- "group",
400
- {
401
- name: "Pinned filters",
402
- hidden: true
403
- }
404
- );
405
- const suggestions = (0, import_react.within)(pinnedGroup).getAllByRole(
406
- "group",
407
- {
408
- hidden: true,
409
- name(_accessibleName, element) {
410
- return element.getAttribute(
411
- "data-strato-filter-field-virtual-focus-type"
412
- ) === "pinned-suggestion";
413
- }
414
- }
415
- );
416
- return suggestions.map((el) => new FilterFieldPinnedSuggestion(el));
417
- } catch {
418
- return [];
419
- }
420
- }
421
- return [];
422
- }
423
- /** Paste text at the current cursor position */
424
- async paste(text, cursorIndex) {
425
- await this.moveCursorTo(cursorIndex ?? -1);
426
- await (0, import_setup_user_event.setupUserEvent)({
427
- pointerEventsCheck: import_user_event.PointerEventsCheckLevel.Never
428
- }).paste(text);
429
- if ((0, import_isFakeTimersEnabled.isFakeTimersEnabled)()) {
430
- await (0, import_react.act)(async () => {
431
- jest.runOnlyPendingTimers();
432
- });
433
- }
434
- }
435
- }
436
- function getFilterFieldHelper(dataTestId) {
437
- return new FilterFieldHelper(dataTestId);
438
- }
30
+ const helpers = (0, import_filter_field.createFilterFieldHelpers)({
31
+ isFakeTimersEnabled: import_isFakeTimersEnabled.isFakeTimersEnabled,
32
+ runOnlyPendingTimers: () => jest.runOnlyPendingTimers(),
33
+ setupUserEvent: import_setup_user_event.setupUserEvent
34
+ });
35
+ const getFilterFieldHelper = helpers.getFilterFieldHelper;
@@ -212,17 +212,7 @@ class DataTableRowSelectionHelper {
212
212
  }
213
213
  async getSelectAllState() {
214
214
  const checkbox = await this.getCheckboxSelectAll();
215
- const value = checkbox.getAttribute("aria-checked");
216
- if (value === "true") {
217
- return true;
218
- } else if (value === "false") {
219
- return false;
220
- } else if (value === "mixed") {
221
- return "indeterminate";
222
- }
223
- throw new Error(
224
- "Could not determine the state of the select all checkbox."
225
- );
215
+ return checkbox.indeterminate === true ? "indeterminate" : checkbox.checked;
226
216
  }
227
217
  async toggleSelectAll() {
228
218
  const checkbox = await this.getCheckboxSelectAll();
@@ -39,5 +39,5 @@ function setupUserEvent(options = {}) {
39
39
  advanceTimers: jest.runOnlyPendingTimers
40
40
  });
41
41
  }
42
- return import_user_event.default.setup();
42
+ return import_user_event.default.setup(options);
43
43
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dynatrace/strato-components-testing",
3
- "version": "3.11.2",
3
+ "version": "3.12.0",
4
4
  "private": false,
5
5
  "license": "Apache-2.0",
6
6
  "types": "./index.d.ts",
@@ -65,7 +65,7 @@
65
65
  }
66
66
  },
67
67
  "peerDependencies": {
68
- "@dynatrace/strato-components": "^3.11.2",
68
+ "@dynatrace/strato-components": "^3.12.0",
69
69
  "@testing-library/react": "^16.0.0",
70
70
  "@testing-library/user-event": "^14.0.0",
71
71
  "framer-motion": "^11.3.19 || ^12.0.0",
@@ -74,7 +74,7 @@
74
74
  "react-dom": "^18.0.0 || ^19.0.0",
75
75
  "react-intl": "^6.0.8 || ^7.0.0",
76
76
  "type-fest": "^5.0.0",
77
- "vitest": "^1.0.0 || ^2.0.0 || ^3.0.0"
77
+ "vitest": "^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0"
78
78
  },
79
79
  "peerDependenciesMeta": {
80
80
  "jest": {