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