@elastic/eui-test-helpers 2.1.0 → 2.2.0-snapshot.1793244789306

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 (84) hide show
  1. package/README.md +6 -0
  2. package/lib/cjs/components/call_out/selectors.d.ts +22 -0
  3. package/lib/cjs/components/call_out/selectors.js +36 -0
  4. package/lib/cjs/components/form/field_search/selectors.d.ts +11 -0
  5. package/lib/cjs/components/form/field_search/selectors.js +25 -0
  6. package/lib/cjs/components/pagination/selectors.d.ts +21 -0
  7. package/lib/cjs/components/pagination/selectors.js +35 -0
  8. package/lib/cjs/components/search_bar/selectors.d.ts +11 -0
  9. package/lib/cjs/components/search_bar/selectors.js +25 -0
  10. package/lib/cjs/components/side_nav/selectors.d.ts +21 -0
  11. package/lib/cjs/components/side_nav/selectors.js +35 -0
  12. package/lib/cjs/components/table/selectors.d.ts +15 -0
  13. package/lib/cjs/components/table/selectors.js +29 -0
  14. package/lib/cjs/index.d.ts +6 -0
  15. package/lib/cjs/index.js +66 -24
  16. package/lib/cjs/playwright/components/basic_table/object.d.ts +7 -12
  17. package/lib/cjs/playwright/components/basic_table/object.js +7 -13
  18. package/lib/cjs/playwright/components/call_out/object.d.ts +36 -0
  19. package/lib/cjs/playwright/components/call_out/object.js +84 -0
  20. package/lib/cjs/playwright/components/form/field_search/object.d.ts +21 -0
  21. package/lib/cjs/playwright/components/form/field_search/object.js +51 -0
  22. package/lib/cjs/playwright/components/pagination/object.d.ts +37 -0
  23. package/lib/cjs/playwright/components/pagination/object.js +121 -0
  24. package/lib/cjs/playwright/components/search_bar/object.d.ts +12 -0
  25. package/lib/cjs/playwright/components/search_bar/object.js +26 -0
  26. package/lib/cjs/playwright/components/side_nav/object.d.ts +34 -0
  27. package/lib/cjs/playwright/components/side_nav/object.js +84 -0
  28. package/lib/cjs/playwright/components/table/object.d.ts +28 -0
  29. package/lib/cjs/playwright/components/table/object.js +57 -0
  30. package/lib/cjs/selectors.d.ts +42 -0
  31. package/lib/cjs/selectors.js +42 -30
  32. package/lib/esm/components/call_out/selectors.d.ts +22 -0
  33. package/lib/esm/components/call_out/selectors.js +30 -0
  34. package/lib/esm/components/call_out/selectors.js.map +1 -0
  35. package/lib/esm/components/form/field_search/selectors.d.ts +11 -0
  36. package/lib/esm/components/form/field_search/selectors.js +19 -0
  37. package/lib/esm/components/form/field_search/selectors.js.map +1 -0
  38. package/lib/esm/components/pagination/selectors.d.ts +21 -0
  39. package/lib/esm/components/pagination/selectors.js +29 -0
  40. package/lib/esm/components/pagination/selectors.js.map +1 -0
  41. package/lib/esm/components/search_bar/selectors.d.ts +11 -0
  42. package/lib/esm/components/search_bar/selectors.js +19 -0
  43. package/lib/esm/components/search_bar/selectors.js.map +1 -0
  44. package/lib/esm/components/side_nav/selectors.d.ts +21 -0
  45. package/lib/esm/components/side_nav/selectors.js +29 -0
  46. package/lib/esm/components/side_nav/selectors.js.map +1 -0
  47. package/lib/esm/components/table/selectors.d.ts +15 -0
  48. package/lib/esm/components/table/selectors.js +23 -0
  49. package/lib/esm/components/table/selectors.js.map +1 -0
  50. package/lib/esm/index.d.ts +6 -0
  51. package/lib/esm/index.js +6 -0
  52. package/lib/esm/index.js.map +1 -1
  53. package/lib/esm/playwright/components/basic_table/object.d.ts +7 -12
  54. package/lib/esm/playwright/components/basic_table/object.js +7 -15
  55. package/lib/esm/playwright/components/basic_table/object.js.map +1 -1
  56. package/lib/esm/playwright/components/call_out/object.d.ts +36 -0
  57. package/lib/esm/playwright/components/call_out/object.js +72 -0
  58. package/lib/esm/playwright/components/call_out/object.js.map +1 -0
  59. package/lib/esm/playwright/components/form/field_search/object.d.ts +21 -0
  60. package/lib/esm/playwright/components/form/field_search/object.js +41 -0
  61. package/lib/esm/playwright/components/form/field_search/object.js.map +1 -0
  62. package/lib/esm/playwright/components/pagination/object.d.ts +37 -0
  63. package/lib/esm/playwright/components/pagination/object.js +118 -0
  64. package/lib/esm/playwright/components/pagination/object.js.map +1 -0
  65. package/lib/esm/playwright/components/search_bar/object.d.ts +12 -0
  66. package/lib/esm/playwright/components/search_bar/object.js +20 -0
  67. package/lib/esm/playwright/components/search_bar/object.js.map +1 -0
  68. package/lib/esm/playwright/components/side_nav/object.d.ts +34 -0
  69. package/lib/esm/playwright/components/side_nav/object.js +76 -0
  70. package/lib/esm/playwright/components/side_nav/object.js.map +1 -0
  71. package/lib/esm/playwright/components/table/object.d.ts +28 -0
  72. package/lib/esm/playwright/components/table/object.js +46 -0
  73. package/lib/esm/playwright/components/table/object.js.map +1 -0
  74. package/lib/esm/selectors.d.ts +42 -0
  75. package/lib/esm/selectors.js +12 -0
  76. package/lib/esm/selectors.js.map +1 -1
  77. package/package.json +3 -2
  78. package/src/components/basic_table/README.md +1 -0
  79. package/src/components/call_out/README.md +29 -0
  80. package/src/components/form/field_search/README.md +29 -0
  81. package/src/components/pagination/README.md +31 -0
  82. package/src/components/search_bar/README.md +18 -0
  83. package/src/components/side_nav/README.md +31 -0
  84. package/src/components/table/README.md +31 -0
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.EuiCallOutObject = void 0;
7
+ var _base_object = require("../../base_object");
8
+ var _selectors = require("../../../components/call_out/selectors");
9
+ /*
10
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
11
+ * or more contributor license agreements. Licensed under the Elastic License
12
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
13
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
14
+ * Side Public License, v 1.
15
+ */
16
+
17
+ /**
18
+ * Playwright Component Object for {@link
19
+ * https://eui.elastic.co/docs/components/display/callout/ EuiCallOut}.
20
+ *
21
+ * `testSubj` must be set on `EuiCallOut` itself. EUI puts it on the panel
22
+ * root and derives `<subj>__message`, `<subj>__content` and
23
+ * `<subj>__actions` for the inner blocks, which the token based root lookup
24
+ * does not confuse with the root.
25
+ */
26
+ class EuiCallOutObject extends _base_object.BaseObject {
27
+ constructor(scope, testSubj) {
28
+ super(scope, testSubj, _selectors.EuiCallOutSelectors.ROOT_SELECTOR);
29
+ }
30
+
31
+ /** The call out element itself, see {@link panel}. */
32
+ get locator() {
33
+ return this.panel;
34
+ }
35
+
36
+ /** The title text, or an empty string when the call out has no title. */
37
+ async getTitle() {
38
+ return this.textOf(this.panel.locator(_selectors.EuiCallOutSelectors.TITLE_SELECTOR));
39
+ }
40
+
41
+ /** The `text` block, or an empty string when the call out has none. */
42
+ async getText() {
43
+ return this.textOf(this.panel.locator(_selectors.EuiCallOutSelectors.TEXT_SELECTOR));
44
+ }
45
+
46
+ /** The color variant: `primary`, `success`, `warning` or `danger`. */
47
+ async getColor() {
48
+ const className = (await this.panel.getAttribute('class')) ?? '';
49
+ const match = className.match(new RegExp(`\\b${_selectors.EuiCallOutSelectors.COLOR_CLASS_PREFIX}([a-z]+)`));
50
+ if (!match) {
51
+ throw new Error(`EuiCallOut "${this.testSubj}" has no color class, is it an EuiCallOut?`);
52
+ }
53
+ return match[1];
54
+ }
55
+
56
+ /** The dismiss button. Resolves to zero elements without `onDismiss`. */
57
+ get dismissButton() {
58
+ return this.panel.locator(_selectors.EuiCallOutSelectors.DISMISS_BUTTON_SELECTOR).first();
59
+ }
60
+
61
+ /**
62
+ * The root narrowed to the call out element. A multi token subj such as
63
+ * `notice shared` also matches the derived `notice shared__message` block
64
+ * by token, so the class keeps lookups on the panel itself.
65
+ */
66
+ get panel() {
67
+ return this.root.and(this.scope.locator(_selectors.EuiCallOutSelectors.ROOT_SELECTOR));
68
+ }
69
+
70
+ /**
71
+ * Click the dismiss button. What happens next is up to the consumer's
72
+ * `onDismiss`, usually unmounting the call out, so nothing is asserted.
73
+ */
74
+ async dismiss() {
75
+ await this.dismissButton.click();
76
+ }
77
+ async textOf(element) {
78
+ if ((await element.count()) === 0) {
79
+ return '';
80
+ }
81
+ return element.first().innerText();
82
+ }
83
+ }
84
+ exports.EuiCallOutObject = EuiCallOutObject;
@@ -0,0 +1,21 @@
1
+ import { BaseObject, type ObjectScope } from '../../../base_object';
2
+ /**
3
+ * Playwright Component Object for {@link
4
+ * https://eui.elastic.co/docs/components/forms/search-and-filter/search/ EuiFieldSearch}.
5
+ *
6
+ * `testSubj` must be set on `EuiFieldSearch` itself, EUI spreads it onto
7
+ * the `<input>`. `EuiSearchBar` renders this input for its box, see
8
+ * `EuiSearchBarObject`.
9
+ */
10
+ export declare class EuiFieldSearchObject extends BaseObject {
11
+ constructor(scope: ObjectScope, testSubj: string, componentSelector?: string);
12
+ /**
13
+ * Replace the text and submit it with Enter, which triggers `onSearch` for
14
+ * both the incremental and the plain variant.
15
+ */
16
+ setQuery(text: string): Promise<void>;
17
+ /** The current text of the input. */
18
+ getQuery(): Promise<string>;
19
+ /** Empty the input and submit, so `onSearch` receives an empty query. */
20
+ clear(): Promise<void>;
21
+ }
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.EuiFieldSearchObject = void 0;
7
+ var _test = require("@playwright/test");
8
+ var _base_object = require("../../../base_object");
9
+ var _selectors = require("../../../../components/form/field_search/selectors");
10
+ /*
11
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
12
+ * or more contributor license agreements. Licensed under the Elastic License
13
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
14
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
15
+ * Side Public License, v 1.
16
+ */
17
+
18
+ /**
19
+ * Playwright Component Object for {@link
20
+ * https://eui.elastic.co/docs/components/forms/search-and-filter/search/ EuiFieldSearch}.
21
+ *
22
+ * `testSubj` must be set on `EuiFieldSearch` itself, EUI spreads it onto
23
+ * the `<input>`. `EuiSearchBar` renders this input for its box, see
24
+ * `EuiSearchBarObject`.
25
+ */
26
+ class EuiFieldSearchObject extends _base_object.BaseObject {
27
+ constructor(scope, testSubj, componentSelector = _selectors.EuiFieldSearchSelectors.ROOT_SELECTOR) {
28
+ super(scope, testSubj, componentSelector);
29
+ }
30
+
31
+ /**
32
+ * Replace the text and submit it with Enter, which triggers `onSearch` for
33
+ * both the incremental and the plain variant.
34
+ */
35
+ async setQuery(text) {
36
+ await this.root.fill(text);
37
+ await (0, _test.expect)(this.root).toHaveValue(text);
38
+ await this.root.press('Enter');
39
+ }
40
+
41
+ /** The current text of the input. */
42
+ async getQuery() {
43
+ return this.root.inputValue();
44
+ }
45
+
46
+ /** Empty the input and submit, so `onSearch` receives an empty query. */
47
+ async clear() {
48
+ await this.setQuery('');
49
+ }
50
+ }
51
+ exports.EuiFieldSearchObject = EuiFieldSearchObject;
@@ -0,0 +1,37 @@
1
+ import { BaseObject, type ObjectScope } from '../../base_object';
2
+ /**
3
+ * Playwright Component Object for {@link
4
+ * https://eui.elastic.co/docs/components/navigation/pagination/ EuiPagination}.
5
+ *
6
+ * `testSubj` must be set on `EuiPagination` itself, EUI spreads it onto the
7
+ * `<nav>`. Page indexes are 0-based, matching EUI's `activePage` and the
8
+ * `pagination-button-<index>` test subjs. Covers the numbered and the
9
+ * compressed variant.
10
+ */
11
+ export declare class EuiPaginationObject extends BaseObject {
12
+ constructor(scope: ObjectScope, testSubj: string);
13
+ /** The 0-based index of the active page. */
14
+ getActivePage(): Promise<number>;
15
+ /** The total number of pages. */
16
+ getPageCount(): Promise<number>;
17
+ /**
18
+ * Go to the page at the 0-based `index` and wait for it to become active.
19
+ * Clicks the page button when EUI renders it, otherwise steps through
20
+ * next or previous until it does. A no-op if already active. Throws if
21
+ * `index` is not a page, or the page never becomes active.
22
+ */
23
+ goToPage(index: number): Promise<void>;
24
+ /** Click the next arrow and wait for the active page to advance. */
25
+ next(): Promise<void>;
26
+ /** Click the previous arrow and wait for the active page to go back. */
27
+ previous(): Promise<void>;
28
+ private pageButton;
29
+ private arrow;
30
+ private isCompressed;
31
+ /**
32
+ * The compressed "page of total" numbers as [page, total]. Translations may
33
+ * order the two the other way round, and the page is never above the total,
34
+ * so the smaller one is the page.
35
+ */
36
+ private compressedNumbers;
37
+ }
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.EuiPaginationObject = void 0;
7
+ var _test = require("@playwright/test");
8
+ var _base_object = require("../../base_object");
9
+ var _selectors = require("../../../components/pagination/selectors");
10
+ /*
11
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
12
+ * or more contributor license agreements. Licensed under the Elastic License
13
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
14
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
15
+ * Side Public License, v 1.
16
+ */
17
+
18
+ /**
19
+ * Playwright Component Object for {@link
20
+ * https://eui.elastic.co/docs/components/navigation/pagination/ EuiPagination}.
21
+ *
22
+ * `testSubj` must be set on `EuiPagination` itself, EUI spreads it onto the
23
+ * `<nav>`. Page indexes are 0-based, matching EUI's `activePage` and the
24
+ * `pagination-button-<index>` test subjs. Covers the numbered and the
25
+ * compressed variant.
26
+ */
27
+ class EuiPaginationObject extends _base_object.BaseObject {
28
+ constructor(scope, testSubj) {
29
+ super(scope, testSubj, _selectors.EuiPaginationSelectors.ROOT_SELECTOR);
30
+ }
31
+
32
+ /** The 0-based index of the active page. */
33
+ async getActivePage() {
34
+ if (await this.isCompressed()) {
35
+ const [page] = await this.compressedNumbers();
36
+ return page - 1;
37
+ }
38
+ const text = await this.root.locator(_selectors.EuiPaginationSelectors.ACTIVE_PAGE_BUTTON_SELECTOR).innerText();
39
+ return Number(text) - 1;
40
+ }
41
+
42
+ /** The total number of pages. */
43
+ async getPageCount() {
44
+ if (await this.isCompressed()) {
45
+ const [, total] = await this.compressedNumbers();
46
+ return total;
47
+ }
48
+ // EUI always renders the last page's button, so its label is the count.
49
+ return Number(await this.root.locator(_selectors.EuiPaginationSelectors.PAGE_BUTTON_SELECTOR).last().innerText());
50
+ }
51
+
52
+ /**
53
+ * Go to the page at the 0-based `index` and wait for it to become active.
54
+ * Clicks the page button when EUI renders it, otherwise steps through
55
+ * next or previous until it does. A no-op if already active. Throws if
56
+ * `index` is not a page, or the page never becomes active.
57
+ */
58
+ async goToPage(index) {
59
+ const pageCount = await this.getPageCount();
60
+ if (!Number.isInteger(index) || index < 0 || index >= pageCount) {
61
+ throw new Error(`EuiPagination "${this.testSubj}" has ${pageCount} pages, page index ${index} is out of range.`);
62
+ }
63
+ for (let step = 0; step < pageCount; step++) {
64
+ const active = await this.getActivePage();
65
+ if (active === index) {
66
+ return;
67
+ }
68
+ const button = this.pageButton(index);
69
+ if ((await button.count()) > 0) {
70
+ await button.click();
71
+ } else if (index > active) {
72
+ await this.arrow(_selectors.EuiPaginationSelectors.NEXT_BUTTON_TEST_SUBJ).click();
73
+ } else {
74
+ await this.arrow(_selectors.EuiPaginationSelectors.PREVIOUS_BUTTON_TEST_SUBJ).click();
75
+ }
76
+ await _test.expect.poll(() => this.getActivePage()).not.toBe(active);
77
+ }
78
+ if ((await this.getActivePage()) !== index) {
79
+ throw new Error(`EuiPagination "${this.testSubj}" did not reach page index ${index} after ${pageCount} steps.`);
80
+ }
81
+ }
82
+
83
+ /** Click the next arrow and wait for the active page to advance. */
84
+ async next() {
85
+ const active = await this.getActivePage();
86
+ await this.arrow(_selectors.EuiPaginationSelectors.NEXT_BUTTON_TEST_SUBJ).click();
87
+ await _test.expect.poll(() => this.getActivePage()).toBe(active + 1);
88
+ }
89
+
90
+ /** Click the previous arrow and wait for the active page to go back. */
91
+ async previous() {
92
+ const active = await this.getActivePage();
93
+ await this.arrow(_selectors.EuiPaginationSelectors.PREVIOUS_BUTTON_TEST_SUBJ).click();
94
+ await _test.expect.poll(() => this.getActivePage()).toBe(active - 1);
95
+ }
96
+ pageButton(index) {
97
+ return this.root.getByTestId(`${_selectors.EuiPaginationSelectors.PAGE_BUTTON_TEST_SUBJ_PREFIX}${index}`);
98
+ }
99
+ arrow(testSubj) {
100
+ return this.root.getByTestId(testSubj);
101
+ }
102
+ async isCompressed() {
103
+ // count() does not wait, so make sure the nav has rendered first.
104
+ await this.root.waitFor({
105
+ state: 'visible'
106
+ });
107
+ return (await this.root.locator(_selectors.EuiPaginationSelectors.COMPRESSED_TEXT_SELECTOR).count()) > 0;
108
+ }
109
+
110
+ /**
111
+ * The compressed "page of total" numbers as [page, total]. Translations may
112
+ * order the two the other way round, and the page is never above the total,
113
+ * so the smaller one is the page.
114
+ */
115
+ async compressedNumbers() {
116
+ const texts = await this.root.locator(_selectors.EuiPaginationSelectors.COMPRESSED_TEXT_SELECTOR).locator('span').allInnerTexts();
117
+ const numbers = texts.map(Number);
118
+ return [Math.min(...numbers), Math.max(...numbers)];
119
+ }
120
+ }
121
+ exports.EuiPaginationObject = EuiPaginationObject;
@@ -0,0 +1,12 @@
1
+ import { EuiFieldSearchObject } from '../form/field_search/object';
2
+ /**
3
+ * Playwright Component Object for {@link
4
+ * https://eui.elastic.co/docs/components/forms/search-and-filter/search-bar/ EuiSearchBar}.
5
+ *
6
+ * The search bar has no root of its own, the consumer's `data-test-subj` is
7
+ * passed through the `box` prop onto the `EuiFieldSearch` input. So this is
8
+ * the field search object under the component's own name. Set
9
+ * `box={{ 'data-test-subj': 'mySearchBar' }}` and construct with that subj.
10
+ */
11
+ export declare class EuiSearchBarObject extends EuiFieldSearchObject {
12
+ }
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.EuiSearchBarObject = void 0;
7
+ var _object = require("../form/field_search/object");
8
+ /*
9
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
10
+ * or more contributor license agreements. Licensed under the Elastic License
11
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
12
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
13
+ * Side Public License, v 1.
14
+ */
15
+
16
+ /**
17
+ * Playwright Component Object for {@link
18
+ * https://eui.elastic.co/docs/components/forms/search-and-filter/search-bar/ EuiSearchBar}.
19
+ *
20
+ * The search bar has no root of its own, the consumer's `data-test-subj` is
21
+ * passed through the `box` prop onto the `EuiFieldSearch` input. So this is
22
+ * the field search object under the component's own name. Set
23
+ * `box={{ 'data-test-subj': 'mySearchBar' }}` and construct with that subj.
24
+ */
25
+ class EuiSearchBarObject extends _object.EuiFieldSearchObject {}
26
+ exports.EuiSearchBarObject = EuiSearchBarObject;
@@ -0,0 +1,34 @@
1
+ import { type Locator } from '@playwright/test';
2
+ import { BaseObject, type ObjectScope } from '../../base_object';
3
+ /**
4
+ * Playwright Component Object for {@link
5
+ * https://eui.elastic.co/docs/components/navigation/side-nav/ EuiSideNav}.
6
+ *
7
+ * `testSubj` must be set on `EuiSideNav` itself, EUI spreads it onto the
8
+ * `<nav>`. Items are addressed by their exact label. Closed branches are
9
+ * not in the DOM, expand their parent first.
10
+ */
11
+ export declare class EuiSideNavObject extends BaseObject {
12
+ constructor(scope: ObjectScope, testSubj: string);
13
+ /** The labels of every rendered item, in document order. */
14
+ getItems(): Promise<string[]>;
15
+ /**
16
+ * The clickable element of the item with exactly this label. Matches the
17
+ * label span, so icon text does not interfere, then climbs to its button.
18
+ * Chained from `root`, so it stays in the root's frame.
19
+ */
20
+ item(label: string): Locator;
21
+ /**
22
+ * Click the item with this label. Selection is owned by the consumer
23
+ * (usually a route change), so nothing is asserted afterwards.
24
+ */
25
+ select(label: string): Promise<void>;
26
+ /** The label of the selected item, or null when none is selected. */
27
+ getSelected(): Promise<string | null>;
28
+ /**
29
+ * Expand an accordion item (one with children and no link or click
30
+ * handler) and wait for its children to render. A no-op if already open.
31
+ */
32
+ expand(label: string): Promise<void>;
33
+ private isOpen;
34
+ }
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.EuiSideNavObject = void 0;
7
+ var _test = require("@playwright/test");
8
+ var _base_object = require("../../base_object");
9
+ var _selectors = require("../../../components/side_nav/selectors");
10
+ /*
11
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
12
+ * or more contributor license agreements. Licensed under the Elastic License
13
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
14
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
15
+ * Side Public License, v 1.
16
+ */
17
+
18
+ /**
19
+ * Playwright Component Object for {@link
20
+ * https://eui.elastic.co/docs/components/navigation/side-nav/ EuiSideNav}.
21
+ *
22
+ * `testSubj` must be set on `EuiSideNav` itself, EUI spreads it onto the
23
+ * `<nav>`. Items are addressed by their exact label. Closed branches are
24
+ * not in the DOM, expand their parent first.
25
+ */
26
+ class EuiSideNavObject extends _base_object.BaseObject {
27
+ constructor(scope, testSubj) {
28
+ super(scope, testSubj, _selectors.EuiSideNavSelectors.ROOT_SELECTOR);
29
+ }
30
+
31
+ /** The labels of every rendered item, in document order. */
32
+ async getItems() {
33
+ return this.root.locator(_selectors.EuiSideNavSelectors.ITEM_LABEL_SELECTOR).allInnerTexts();
34
+ }
35
+
36
+ /**
37
+ * The clickable element of the item with exactly this label. Matches the
38
+ * label span, so icon text does not interfere, then climbs to its button.
39
+ * Chained from `root`, so it stays in the root's frame.
40
+ */
41
+ item(label) {
42
+ return this.root.locator(_selectors.EuiSideNavSelectors.ITEM_LABEL_SELECTOR).filter({
43
+ hasText: new RegExp(`^${escapeRegExp(label)}$`)
44
+ }).locator(ITEM_BUTTON_ANCESTOR_XPATH);
45
+ }
46
+
47
+ /**
48
+ * Click the item with this label. Selection is owned by the consumer
49
+ * (usually a route change), so nothing is asserted afterwards.
50
+ */
51
+ async select(label) {
52
+ await this.item(label).click();
53
+ }
54
+
55
+ /** The label of the selected item, or null when none is selected. */
56
+ async getSelected() {
57
+ const selected = this.root.locator(_selectors.EuiSideNavSelectors.SELECTED_ITEM_BUTTON_SELECTOR).locator(_selectors.EuiSideNavSelectors.ITEM_LABEL_SELECTOR);
58
+ if ((await selected.count()) === 0) {
59
+ return null;
60
+ }
61
+ return selected.first().innerText();
62
+ }
63
+
64
+ /**
65
+ * Expand an accordion item (one with children and no link or click
66
+ * handler) and wait for its children to render. A no-op if already open.
67
+ */
68
+ async expand(label) {
69
+ const button = this.item(label);
70
+ if (await this.isOpen(button)) {
71
+ return;
72
+ }
73
+ await button.click();
74
+ await _test.expect.poll(() => this.isOpen(button)).toBe(true);
75
+ }
76
+ isOpen(button) {
77
+ return button.evaluate((el, openClass) => el.matches(openClass), _selectors.EuiSideNavSelectors.OPEN_ITEM_BUTTON_SELECTOR);
78
+ }
79
+ }
80
+
81
+ /** Nearest ancestor carrying the exact `euiSideNavItemButton` class token. */
82
+ exports.EuiSideNavObject = EuiSideNavObject;
83
+ const ITEM_BUTTON_ANCESTOR_XPATH = "xpath=ancestor::*[contains(concat(' ', normalize-space(@class), ' '), ' euiSideNavItemButton ')][1]";
84
+ const escapeRegExp = text => text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
@@ -0,0 +1,28 @@
1
+ import type { Locator } from '@playwright/test';
2
+ import { BaseObject, type ObjectScope } from '../../base_object';
3
+ /**
4
+ * Playwright Component Object for {@link
5
+ * https://eui.elastic.co/docs/components/tabular-content/tables/ EuiTable},
6
+ * the low level table built from `EuiTableHeader`, `EuiTableRow` and
7
+ * `EuiTableRowCell`. `EuiBasicTableObject` extends this for the
8
+ * `EuiBasicTable` and `EuiInMemoryTable` wrappers.
9
+ *
10
+ * `testSubj` must be set on `EuiTable` itself, EUI spreads it onto the
11
+ * `<table>`. Columns are addressed by position since a plain table has no
12
+ * field names.
13
+ */
14
+ export declare class EuiTableObject extends BaseObject {
15
+ constructor(scope: ObjectScope, testSubj: string, componentSelector?: string);
16
+ /** The body rows. */
17
+ get rows(): Locator;
18
+ /** The header cells, in column order. */
19
+ get headerCells(): Locator;
20
+ /**
21
+ * The cells of one column across all body rows, by 0-based position.
22
+ * Direct children only, so a table nested in a cell is not matched. Matches
23
+ * both `<td>` and `<th>`, EUI renders a row header cell as `<th scope="row">`.
24
+ */
25
+ column(index: number): Locator;
26
+ /** One body cell by 0-based row and column position. */
27
+ cell(row: number, column: number): Locator;
28
+ }
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.EuiTableObject = void 0;
7
+ var _base_object = require("../../base_object");
8
+ var _selectors = require("../../../components/table/selectors");
9
+ /*
10
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
11
+ * or more contributor license agreements. Licensed under the Elastic License
12
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
13
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
14
+ * Side Public License, v 1.
15
+ */
16
+
17
+ /**
18
+ * Playwright Component Object for {@link
19
+ * https://eui.elastic.co/docs/components/tabular-content/tables/ EuiTable},
20
+ * the low level table built from `EuiTableHeader`, `EuiTableRow` and
21
+ * `EuiTableRowCell`. `EuiBasicTableObject` extends this for the
22
+ * `EuiBasicTable` and `EuiInMemoryTable` wrappers.
23
+ *
24
+ * `testSubj` must be set on `EuiTable` itself, EUI spreads it onto the
25
+ * `<table>`. Columns are addressed by position since a plain table has no
26
+ * field names.
27
+ */
28
+ class EuiTableObject extends _base_object.BaseObject {
29
+ constructor(scope, testSubj, componentSelector = _selectors.EuiTableSelectors.ROOT_SELECTOR) {
30
+ super(scope, testSubj, componentSelector);
31
+ }
32
+
33
+ /** The body rows. */
34
+ get rows() {
35
+ return this.root.locator(_selectors.EuiTableSelectors.ROW_SELECTOR);
36
+ }
37
+
38
+ /** The header cells, in column order. */
39
+ get headerCells() {
40
+ return this.root.locator(_selectors.EuiTableSelectors.HEADER_CELL_SELECTOR);
41
+ }
42
+
43
+ /**
44
+ * The cells of one column across all body rows, by 0-based position.
45
+ * Direct children only, so a table nested in a cell is not matched. Matches
46
+ * both `<td>` and `<th>`, EUI renders a row header cell as `<th scope="row">`.
47
+ */
48
+ column(index) {
49
+ return this.rows.locator(`> :is(td, th):nth-child(${index + 1})`);
50
+ }
51
+
52
+ /** One body cell by 0-based row and column position. */
53
+ cell(row, column) {
54
+ return this.rows.nth(row).locator(`> :is(td, th):nth-child(${column + 1})`);
55
+ }
56
+ }
57
+ exports.EuiTableObject = EuiTableObject;
@@ -15,6 +15,14 @@ export declare const selectors: {
15
15
  ROW_SELECTOR: string;
16
16
  HEADER_CELL_SELECTOR_PREFIX: string;
17
17
  };
18
+ readonly callOut: {
19
+ ROOT_SELECTOR: string;
20
+ TITLE_SELECTOR: string;
21
+ TEXT_SELECTOR: string;
22
+ COLOR_CLASS_PREFIX: string;
23
+ DISMISS_BUTTON_TEST_SUBJ: string;
24
+ DISMISS_BUTTON_SELECTOR: string;
25
+ };
18
26
  readonly colorPicker: {
19
27
  ANCHOR_TEST_SUBJ: string;
20
28
  ANCHOR_SELECTOR: string;
@@ -57,6 +65,10 @@ export declare const selectors: {
57
65
  HANDLE_SELECTOR: string;
58
66
  ITEM_SELECTOR: string;
59
67
  };
68
+ readonly fieldSearch: {
69
+ ROOT_SELECTOR: string;
70
+ CLEAR_BUTTON_TEST_SUBJ: string;
71
+ };
60
72
  readonly filterButton: {
61
73
  ROOT_SELECTOR: string;
62
74
  NOTIFICATION_SELECTOR: string;
@@ -71,6 +83,17 @@ export declare const selectors: {
71
83
  ROOT_SELECTOR: string;
72
84
  CLOSE_BUTTON_SELECTOR: string;
73
85
  };
86
+ readonly pagination: {
87
+ ROOT_SELECTOR: string;
88
+ PAGE_BUTTON_SELECTOR: string;
89
+ ACTIVE_PAGE_BUTTON_SELECTOR: string;
90
+ COMPRESSED_TEXT_SELECTOR: string;
91
+ PAGE_BUTTON_TEST_SUBJ_PREFIX: string;
92
+ FIRST_BUTTON_TEST_SUBJ: string;
93
+ PREVIOUS_BUTTON_TEST_SUBJ: string;
94
+ NEXT_BUTTON_TEST_SUBJ: string;
95
+ LAST_BUTTON_TEST_SUBJ: string;
96
+ };
74
97
  readonly popover: {
75
98
  TOGGLE_SELECTOR: string;
76
99
  panelFor: (id: string) => string;
@@ -79,10 +102,23 @@ export declare const selectors: {
79
102
  SLIDER_SELECTOR: string;
80
103
  NUMBER_INPUT_SELECTOR: string;
81
104
  };
105
+ readonly searchBar: {
106
+ SEARCH_HOLDER_SELECTOR: string;
107
+ FILTERS_HOLDER_SELECTOR: string;
108
+ };
82
109
  readonly selectable: {
83
110
  ROOT_SELECTOR: string;
84
111
  SEARCH_SELECTOR: string;
85
112
  };
113
+ readonly sideNav: {
114
+ ROOT_SELECTOR: string;
115
+ ITEM_SELECTOR: string;
116
+ ITEM_BUTTON_SELECTOR: string;
117
+ SELECTED_ITEM_BUTTON_SELECTOR: string;
118
+ OPEN_ITEM_BUTTON_SELECTOR: string;
119
+ ITEM_LABEL_SELECTOR: string;
120
+ CHILD_ITEMS_SELECTOR: string;
121
+ };
86
122
  readonly superSelect: {
87
123
  ROOT_SELECTOR: string;
88
124
  WRAPPER_SELECTOR: string;
@@ -90,6 +126,12 @@ export declare const selectors: {
90
126
  HIDDEN_INPUT_SELECTOR: string;
91
127
  optionByValue: (value: string) => string;
92
128
  };
129
+ readonly table: {
130
+ ROOT_SELECTOR: string;
131
+ ROW_SELECTOR: string;
132
+ ROW_CELL_SELECTOR: string;
133
+ HEADER_CELL_SELECTOR: string;
134
+ };
93
135
  readonly globalToastList: {
94
136
  ROOT_SELECTOR: string;
95
137
  TOAST_SELECTOR: string;