@elastic/eui-test-helpers 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/lib/cjs/components/selectable/selectors.d.ts +11 -0
- package/lib/cjs/components/selectable/selectors.js +25 -0
- package/lib/cjs/index.d.ts +1 -0
- package/lib/cjs/index.js +8 -1
- package/lib/cjs/playwright/components/selectable/object.d.ts +53 -0
- package/lib/cjs/playwright/components/selectable/object.js +92 -0
- package/lib/cjs/selectors.d.ts +1 -0
- package/lib/cjs/selectors.js +8 -1
- package/lib/esm/components/selectable/selectors.d.ts +11 -0
- package/lib/esm/components/selectable/selectors.js +19 -0
- package/lib/esm/components/selectable/selectors.js.map +1 -0
- package/lib/esm/index.d.ts +1 -0
- package/lib/esm/index.js +1 -0
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/playwright/components/selectable/object.d.ts +53 -0
- package/lib/esm/playwright/components/selectable/object.js +83 -0
- package/lib/esm/playwright/components/selectable/object.js.map +1 -0
- package/lib/esm/selectors.d.ts +1 -0
- package/lib/esm/selectors.js +1 -0
- package/lib/esm/selectors.js.map +1 -1
- package/package.json +1 -1
- package/src/components/selectable/README.md +27 -0
package/README.md
CHANGED
|
@@ -50,6 +50,7 @@ their own version at runtime.
|
|
|
50
50
|
| `EuiDataGridObject` | [src/components/datagrid/README.md](src/components/datagrid/README.md) |
|
|
51
51
|
| `EuiSuperSelectObject` | [src/components/form/super_select/README.md](src/components/form/super_select/README.md) |
|
|
52
52
|
| `EuiGlobalToastListObject` | [src/components/toast/README.md](src/components/toast/README.md) |
|
|
53
|
+
| `EuiSelectableObject` | [src/components/selectable/README.md](src/components/selectable/README.md) |
|
|
53
54
|
|
|
54
55
|
## Contributing
|
|
55
56
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable selectors for
|
|
3
|
+
* {@link https://eui.elastic.co/docs/components/forms/selection/selectable/|EuiSelectable}.
|
|
4
|
+
* `*_SELECTOR` values are CSS.
|
|
5
|
+
*/
|
|
6
|
+
export declare const EuiSelectableSelectors: {
|
|
7
|
+
/** Root element (the `.euiSelectable` container carrying the consumer's `data-test-subj`). */
|
|
8
|
+
ROOT_SELECTOR: string;
|
|
9
|
+
/** The search box, present only when the selectable is `searchable`. */
|
|
10
|
+
SEARCH_SELECTOR: string;
|
|
11
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.EuiSelectableSelectors = void 0;
|
|
7
|
+
/*
|
|
8
|
+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
9
|
+
* or more contributor license agreements. Licensed under the Elastic License
|
|
10
|
+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
11
|
+
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
12
|
+
* Side Public License, v 1.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Stable selectors for
|
|
17
|
+
* {@link https://eui.elastic.co/docs/components/forms/selection/selectable/|EuiSelectable}.
|
|
18
|
+
* `*_SELECTOR` values are CSS.
|
|
19
|
+
*/
|
|
20
|
+
const EuiSelectableSelectors = exports.EuiSelectableSelectors = {
|
|
21
|
+
/** Root element (the `.euiSelectable` container carrying the consumer's `data-test-subj`). */
|
|
22
|
+
ROOT_SELECTOR: '.euiSelectable',
|
|
23
|
+
/** The search box, present only when the selectable is `searchable`. */
|
|
24
|
+
SEARCH_SELECTOR: '.euiSelectableSearch'
|
|
25
|
+
};
|
package/lib/cjs/index.d.ts
CHANGED
|
@@ -3,3 +3,4 @@ export { EuiComboBoxObject } from './playwright/components/combo_box/object';
|
|
|
3
3
|
export { EuiDataGridObject } from './playwright/components/datagrid/object';
|
|
4
4
|
export { EuiSuperSelectObject } from './playwright/components/form/super_select/object';
|
|
5
5
|
export { EuiGlobalToastListObject } from './playwright/components/toast/object';
|
|
6
|
+
export { EuiSelectableObject } from './playwright/components/selectable/object';
|
package/lib/cjs/index.js
CHANGED
|
@@ -27,6 +27,12 @@ Object.defineProperty(exports, "EuiGlobalToastListObject", {
|
|
|
27
27
|
return _object4.EuiGlobalToastListObject;
|
|
28
28
|
}
|
|
29
29
|
});
|
|
30
|
+
Object.defineProperty(exports, "EuiSelectableObject", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
get: function () {
|
|
33
|
+
return _object5.EuiSelectableObject;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
30
36
|
Object.defineProperty(exports, "EuiSuperSelectObject", {
|
|
31
37
|
enumerable: true,
|
|
32
38
|
get: function () {
|
|
@@ -37,4 +43,5 @@ var _base_object = require("./playwright/base_object");
|
|
|
37
43
|
var _object = require("./playwright/components/combo_box/object");
|
|
38
44
|
var _object2 = require("./playwright/components/datagrid/object");
|
|
39
45
|
var _object3 = require("./playwright/components/form/super_select/object");
|
|
40
|
-
var _object4 = require("./playwright/components/toast/object");
|
|
46
|
+
var _object4 = require("./playwright/components/toast/object");
|
|
47
|
+
var _object5 = require("./playwright/components/selectable/object");
|
|
@@ -0,0 +1,53 @@
|
|
|
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/forms/selection/selectable/ EuiSelectable}.
|
|
6
|
+
*
|
|
7
|
+
* `testSubj` must match the `data-test-subj` set by the consumer on the
|
|
8
|
+
* `<EuiSelectable>` (EUI spreads it onto the `.euiSelectable` root). When the
|
|
9
|
+
* selectable renders inside a popover the consumer opens, pass that popover as
|
|
10
|
+
* `scope` and drive the open/close from the test — the popover is not this
|
|
11
|
+
* component's concern.
|
|
12
|
+
*/
|
|
13
|
+
export declare class EuiSelectableObject extends BaseObject {
|
|
14
|
+
constructor(scope: ObjectScope, testSubj: string);
|
|
15
|
+
/**
|
|
16
|
+
* The options currently mounted in the list, as a `Locator` so callers keep
|
|
17
|
+
* Playwright auto-retry for count and content assertions
|
|
18
|
+
* (e.g. `expect(options).toHaveCount(3)`). The list is virtualized, so this is
|
|
19
|
+
* the rendered window — `search()` first to filter the target into view
|
|
20
|
+
* rather than scanning a long list.
|
|
21
|
+
*/
|
|
22
|
+
get options(): Locator;
|
|
23
|
+
/**
|
|
24
|
+
* Selects the option with the given label. A no-op if it is already selected.
|
|
25
|
+
* EUI reports that as `aria-checked` for a multi-selection list, or
|
|
26
|
+
* `aria-selected` for a single-selection one, so both are checked.
|
|
27
|
+
*
|
|
28
|
+
* Matches on the option's label element (`.euiSelectableListItem__text`), not
|
|
29
|
+
* its accessible name. `append`/`prepend` badges render in a sibling element,
|
|
30
|
+
* so they are excluded. EUI appends screen-reader state text inside the label
|
|
31
|
+
* element (a checked option reads `"<label> . Checked option."`), which always
|
|
32
|
+
* starts with a `.`, so the match allows an optional `.`-prefixed suffix. That
|
|
33
|
+
* boundary is what keeps `selectOption('New York')` from also matching
|
|
34
|
+
* `New York City`: a real longer label continues with a word, not a `.`.
|
|
35
|
+
*
|
|
36
|
+
* This is for lists in their default state. Once you call `search()`, EUI
|
|
37
|
+
* wraps the matched text in `<mark>` and injects highlight markers, so a label
|
|
38
|
+
* match no longer resolves. On a searched list, select via the option's own
|
|
39
|
+
* `data-test-subj`, or drive it through {@link options} directly.
|
|
40
|
+
*
|
|
41
|
+
* Only matches the plain label. A consumer using a custom `renderOption` to
|
|
42
|
+
* add its own content (e.g. a description) inside the option renders that
|
|
43
|
+
* content in the same label element, which breaks the anchored match. Select
|
|
44
|
+
* those options via {@link options} instead (e.g.
|
|
45
|
+
* `options.filter({ hasText: label })`).
|
|
46
|
+
*/
|
|
47
|
+
selectOption(label: string): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Type into the selectable's search box to filter the options. Throws if the
|
|
50
|
+
* selectable is not searchable (no search box rendered).
|
|
51
|
+
*/
|
|
52
|
+
search(term: string): Promise<void>;
|
|
53
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.EuiSelectableObject = void 0;
|
|
7
|
+
var _base_object = require("../../base_object");
|
|
8
|
+
var _selectors = require("../../../components/selectable/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/forms/selection/selectable/ EuiSelectable}.
|
|
20
|
+
*
|
|
21
|
+
* `testSubj` must match the `data-test-subj` set by the consumer on the
|
|
22
|
+
* `<EuiSelectable>` (EUI spreads it onto the `.euiSelectable` root). When the
|
|
23
|
+
* selectable renders inside a popover the consumer opens, pass that popover as
|
|
24
|
+
* `scope` and drive the open/close from the test — the popover is not this
|
|
25
|
+
* component's concern.
|
|
26
|
+
*/
|
|
27
|
+
class EuiSelectableObject extends _base_object.BaseObject {
|
|
28
|
+
constructor(scope, testSubj) {
|
|
29
|
+
super(scope, testSubj, _selectors.EuiSelectableSelectors.ROOT_SELECTOR);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The options currently mounted in the list, as a `Locator` so callers keep
|
|
34
|
+
* Playwright auto-retry for count and content assertions
|
|
35
|
+
* (e.g. `expect(options).toHaveCount(3)`). The list is virtualized, so this is
|
|
36
|
+
* the rendered window — `search()` first to filter the target into view
|
|
37
|
+
* rather than scanning a long list.
|
|
38
|
+
*/
|
|
39
|
+
get options() {
|
|
40
|
+
return this.root.getByRole('option');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Selects the option with the given label. A no-op if it is already selected.
|
|
45
|
+
* EUI reports that as `aria-checked` for a multi-selection list, or
|
|
46
|
+
* `aria-selected` for a single-selection one, so both are checked.
|
|
47
|
+
*
|
|
48
|
+
* Matches on the option's label element (`.euiSelectableListItem__text`), not
|
|
49
|
+
* its accessible name. `append`/`prepend` badges render in a sibling element,
|
|
50
|
+
* so they are excluded. EUI appends screen-reader state text inside the label
|
|
51
|
+
* element (a checked option reads `"<label> . Checked option."`), which always
|
|
52
|
+
* starts with a `.`, so the match allows an optional `.`-prefixed suffix. That
|
|
53
|
+
* boundary is what keeps `selectOption('New York')` from also matching
|
|
54
|
+
* `New York City`: a real longer label continues with a word, not a `.`.
|
|
55
|
+
*
|
|
56
|
+
* This is for lists in their default state. Once you call `search()`, EUI
|
|
57
|
+
* wraps the matched text in `<mark>` and injects highlight markers, so a label
|
|
58
|
+
* match no longer resolves. On a searched list, select via the option's own
|
|
59
|
+
* `data-test-subj`, or drive it through {@link options} directly.
|
|
60
|
+
*
|
|
61
|
+
* Only matches the plain label. A consumer using a custom `renderOption` to
|
|
62
|
+
* add its own content (e.g. a description) inside the option renders that
|
|
63
|
+
* content in the same label element, which breaks the anchored match. Select
|
|
64
|
+
* those options via {@link options} instead (e.g.
|
|
65
|
+
* `options.filter({ hasText: label })`).
|
|
66
|
+
*/
|
|
67
|
+
async selectOption(label) {
|
|
68
|
+
const escaped = label.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
69
|
+
const labelText = new RegExp(`^${escaped}(\\s*\\..*)?$`);
|
|
70
|
+
const option = this.root.getByRole('option').filter({
|
|
71
|
+
has: this.root.page().locator('.euiSelectableListItem__text', {
|
|
72
|
+
hasText: labelText
|
|
73
|
+
})
|
|
74
|
+
});
|
|
75
|
+
const [ariaChecked, ariaSelected] = await Promise.all([option.getAttribute('aria-checked'), option.getAttribute('aria-selected')]);
|
|
76
|
+
if (ariaChecked === 'true' || ariaSelected === 'true') {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
await option.click();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Type into the selectable's search box to filter the options. Throws if the
|
|
84
|
+
* selectable is not searchable (no search box rendered).
|
|
85
|
+
*/
|
|
86
|
+
async search(term) {
|
|
87
|
+
// `fill()` auto-waits for the search box; if the selectable is not
|
|
88
|
+
// searchable it surfaces a clear locator-timeout on its own.
|
|
89
|
+
await this.root.locator(_selectors.EuiSelectableSelectors.SEARCH_SELECTOR).fill(term);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
exports.EuiSelectableObject = EuiSelectableObject;
|
package/lib/cjs/selectors.d.ts
CHANGED
|
@@ -2,3 +2,4 @@ export { EuiComboBoxSelectors } from './components/combo_box/selectors';
|
|
|
2
2
|
export { EuiDataGridSelectors } from './components/datagrid/selectors';
|
|
3
3
|
export { EuiSuperSelectSelectors } from './components/form/super_select/selectors';
|
|
4
4
|
export { EuiGlobalToastListSelectors } from './components/toast/selectors';
|
|
5
|
+
export { EuiSelectableSelectors } from './components/selectable/selectors';
|
package/lib/cjs/selectors.js
CHANGED
|
@@ -21,6 +21,12 @@ Object.defineProperty(exports, "EuiGlobalToastListSelectors", {
|
|
|
21
21
|
return _selectors4.EuiGlobalToastListSelectors;
|
|
22
22
|
}
|
|
23
23
|
});
|
|
24
|
+
Object.defineProperty(exports, "EuiSelectableSelectors", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function () {
|
|
27
|
+
return _selectors5.EuiSelectableSelectors;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
24
30
|
Object.defineProperty(exports, "EuiSuperSelectSelectors", {
|
|
25
31
|
enumerable: true,
|
|
26
32
|
get: function () {
|
|
@@ -30,4 +36,5 @@ Object.defineProperty(exports, "EuiSuperSelectSelectors", {
|
|
|
30
36
|
var _selectors = require("./components/combo_box/selectors");
|
|
31
37
|
var _selectors2 = require("./components/datagrid/selectors");
|
|
32
38
|
var _selectors3 = require("./components/form/super_select/selectors");
|
|
33
|
-
var _selectors4 = require("./components/toast/selectors");
|
|
39
|
+
var _selectors4 = require("./components/toast/selectors");
|
|
40
|
+
var _selectors5 = require("./components/selectable/selectors");
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable selectors for
|
|
3
|
+
* {@link https://eui.elastic.co/docs/components/forms/selection/selectable/|EuiSelectable}.
|
|
4
|
+
* `*_SELECTOR` values are CSS.
|
|
5
|
+
*/
|
|
6
|
+
export declare const EuiSelectableSelectors: {
|
|
7
|
+
/** Root element (the `.euiSelectable` container carrying the consumer's `data-test-subj`). */
|
|
8
|
+
ROOT_SELECTOR: string;
|
|
9
|
+
/** The search box, present only when the selectable is `searchable`. */
|
|
10
|
+
SEARCH_SELECTOR: string;
|
|
11
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
3
|
+
* or more contributor license agreements. Licensed under the Elastic License
|
|
4
|
+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
5
|
+
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
6
|
+
* Side Public License, v 1.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Stable selectors for
|
|
10
|
+
* {@link https://eui.elastic.co/docs/components/forms/selection/selectable/|EuiSelectable}.
|
|
11
|
+
* `*_SELECTOR` values are CSS.
|
|
12
|
+
*/
|
|
13
|
+
export const EuiSelectableSelectors = {
|
|
14
|
+
/** Root element (the `.euiSelectable` container carrying the consumer's `data-test-subj`). */
|
|
15
|
+
ROOT_SELECTOR: '.euiSelectable',
|
|
16
|
+
/** The search box, present only when the selectable is `searchable`. */
|
|
17
|
+
SEARCH_SELECTOR: '.euiSelectableSearch',
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=selectors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selectors.js","sourceRoot":"","sources":["../../../../src/components/selectable/selectors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,8FAA8F;IAC9F,aAAa,EAAE,gBAAgB;IAE/B,wEAAwE;IACxE,eAAe,EAAE,sBAAsB;CACxC,CAAC"}
|
package/lib/esm/index.d.ts
CHANGED
|
@@ -3,3 +3,4 @@ export { EuiComboBoxObject } from './playwright/components/combo_box/object';
|
|
|
3
3
|
export { EuiDataGridObject } from './playwright/components/datagrid/object';
|
|
4
4
|
export { EuiSuperSelectObject } from './playwright/components/form/super_select/object';
|
|
5
5
|
export { EuiGlobalToastListObject } from './playwright/components/toast/object';
|
|
6
|
+
export { EuiSelectableObject } from './playwright/components/selectable/object';
|
package/lib/esm/index.js
CHANGED
|
@@ -10,4 +10,5 @@ export { EuiComboBoxObject } from './playwright/components/combo_box/object';
|
|
|
10
10
|
export { EuiDataGridObject } from './playwright/components/datagrid/object';
|
|
11
11
|
export { EuiSuperSelectObject } from './playwright/components/form/super_select/object';
|
|
12
12
|
export { EuiGlobalToastListObject } from './playwright/components/toast/object';
|
|
13
|
+
export { EuiSelectableObject } from './playwright/components/selectable/object';
|
|
13
14
|
//# sourceMappingURL=index.js.map
|
package/lib/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAoB,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,kDAAkD,CAAC;AACxF,OAAO,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAoB,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,kDAAkD,CAAC;AACxF,OAAO,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAChF,OAAO,EAAE,mBAAmB,EAAE,MAAM,2CAA2C,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
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/forms/selection/selectable/ EuiSelectable}.
|
|
6
|
+
*
|
|
7
|
+
* `testSubj` must match the `data-test-subj` set by the consumer on the
|
|
8
|
+
* `<EuiSelectable>` (EUI spreads it onto the `.euiSelectable` root). When the
|
|
9
|
+
* selectable renders inside a popover the consumer opens, pass that popover as
|
|
10
|
+
* `scope` and drive the open/close from the test — the popover is not this
|
|
11
|
+
* component's concern.
|
|
12
|
+
*/
|
|
13
|
+
export declare class EuiSelectableObject extends BaseObject {
|
|
14
|
+
constructor(scope: ObjectScope, testSubj: string);
|
|
15
|
+
/**
|
|
16
|
+
* The options currently mounted in the list, as a `Locator` so callers keep
|
|
17
|
+
* Playwright auto-retry for count and content assertions
|
|
18
|
+
* (e.g. `expect(options).toHaveCount(3)`). The list is virtualized, so this is
|
|
19
|
+
* the rendered window — `search()` first to filter the target into view
|
|
20
|
+
* rather than scanning a long list.
|
|
21
|
+
*/
|
|
22
|
+
get options(): Locator;
|
|
23
|
+
/**
|
|
24
|
+
* Selects the option with the given label. A no-op if it is already selected.
|
|
25
|
+
* EUI reports that as `aria-checked` for a multi-selection list, or
|
|
26
|
+
* `aria-selected` for a single-selection one, so both are checked.
|
|
27
|
+
*
|
|
28
|
+
* Matches on the option's label element (`.euiSelectableListItem__text`), not
|
|
29
|
+
* its accessible name. `append`/`prepend` badges render in a sibling element,
|
|
30
|
+
* so they are excluded. EUI appends screen-reader state text inside the label
|
|
31
|
+
* element (a checked option reads `"<label> . Checked option."`), which always
|
|
32
|
+
* starts with a `.`, so the match allows an optional `.`-prefixed suffix. That
|
|
33
|
+
* boundary is what keeps `selectOption('New York')` from also matching
|
|
34
|
+
* `New York City`: a real longer label continues with a word, not a `.`.
|
|
35
|
+
*
|
|
36
|
+
* This is for lists in their default state. Once you call `search()`, EUI
|
|
37
|
+
* wraps the matched text in `<mark>` and injects highlight markers, so a label
|
|
38
|
+
* match no longer resolves. On a searched list, select via the option's own
|
|
39
|
+
* `data-test-subj`, or drive it through {@link options} directly.
|
|
40
|
+
*
|
|
41
|
+
* Only matches the plain label. A consumer using a custom `renderOption` to
|
|
42
|
+
* add its own content (e.g. a description) inside the option renders that
|
|
43
|
+
* content in the same label element, which breaks the anchored match. Select
|
|
44
|
+
* those options via {@link options} instead (e.g.
|
|
45
|
+
* `options.filter({ hasText: label })`).
|
|
46
|
+
*/
|
|
47
|
+
selectOption(label: string): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Type into the selectable's search box to filter the options. Throws if the
|
|
50
|
+
* selectable is not searchable (no search box rendered).
|
|
51
|
+
*/
|
|
52
|
+
search(term: string): Promise<void>;
|
|
53
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
3
|
+
* or more contributor license agreements. Licensed under the Elastic License
|
|
4
|
+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
5
|
+
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
6
|
+
* Side Public License, v 1.
|
|
7
|
+
*/
|
|
8
|
+
import { BaseObject } from '../../base_object';
|
|
9
|
+
import { EuiSelectableSelectors } from '../../../components/selectable/selectors';
|
|
10
|
+
/**
|
|
11
|
+
* Playwright Component Object for {@link
|
|
12
|
+
* https://eui.elastic.co/docs/components/forms/selection/selectable/ EuiSelectable}.
|
|
13
|
+
*
|
|
14
|
+
* `testSubj` must match the `data-test-subj` set by the consumer on the
|
|
15
|
+
* `<EuiSelectable>` (EUI spreads it onto the `.euiSelectable` root). When the
|
|
16
|
+
* selectable renders inside a popover the consumer opens, pass that popover as
|
|
17
|
+
* `scope` and drive the open/close from the test — the popover is not this
|
|
18
|
+
* component's concern.
|
|
19
|
+
*/
|
|
20
|
+
export class EuiSelectableObject extends BaseObject {
|
|
21
|
+
constructor(scope, testSubj) {
|
|
22
|
+
super(scope, testSubj, EuiSelectableSelectors.ROOT_SELECTOR);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The options currently mounted in the list, as a `Locator` so callers keep
|
|
26
|
+
* Playwright auto-retry for count and content assertions
|
|
27
|
+
* (e.g. `expect(options).toHaveCount(3)`). The list is virtualized, so this is
|
|
28
|
+
* the rendered window — `search()` first to filter the target into view
|
|
29
|
+
* rather than scanning a long list.
|
|
30
|
+
*/
|
|
31
|
+
get options() {
|
|
32
|
+
return this.root.getByRole('option');
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Selects the option with the given label. A no-op if it is already selected.
|
|
36
|
+
* EUI reports that as `aria-checked` for a multi-selection list, or
|
|
37
|
+
* `aria-selected` for a single-selection one, so both are checked.
|
|
38
|
+
*
|
|
39
|
+
* Matches on the option's label element (`.euiSelectableListItem__text`), not
|
|
40
|
+
* its accessible name. `append`/`prepend` badges render in a sibling element,
|
|
41
|
+
* so they are excluded. EUI appends screen-reader state text inside the label
|
|
42
|
+
* element (a checked option reads `"<label> . Checked option."`), which always
|
|
43
|
+
* starts with a `.`, so the match allows an optional `.`-prefixed suffix. That
|
|
44
|
+
* boundary is what keeps `selectOption('New York')` from also matching
|
|
45
|
+
* `New York City`: a real longer label continues with a word, not a `.`.
|
|
46
|
+
*
|
|
47
|
+
* This is for lists in their default state. Once you call `search()`, EUI
|
|
48
|
+
* wraps the matched text in `<mark>` and injects highlight markers, so a label
|
|
49
|
+
* match no longer resolves. On a searched list, select via the option's own
|
|
50
|
+
* `data-test-subj`, or drive it through {@link options} directly.
|
|
51
|
+
*
|
|
52
|
+
* Only matches the plain label. A consumer using a custom `renderOption` to
|
|
53
|
+
* add its own content (e.g. a description) inside the option renders that
|
|
54
|
+
* content in the same label element, which breaks the anchored match. Select
|
|
55
|
+
* those options via {@link options} instead (e.g.
|
|
56
|
+
* `options.filter({ hasText: label })`).
|
|
57
|
+
*/
|
|
58
|
+
async selectOption(label) {
|
|
59
|
+
const escaped = label.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
60
|
+
const labelText = new RegExp(`^${escaped}(\\s*\\..*)?$`);
|
|
61
|
+
const option = this.root
|
|
62
|
+
.getByRole('option')
|
|
63
|
+
.filter({ has: this.root.page().locator('.euiSelectableListItem__text', { hasText: labelText }) });
|
|
64
|
+
const [ariaChecked, ariaSelected] = await Promise.all([
|
|
65
|
+
option.getAttribute('aria-checked'),
|
|
66
|
+
option.getAttribute('aria-selected'),
|
|
67
|
+
]);
|
|
68
|
+
if (ariaChecked === 'true' || ariaSelected === 'true') {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
await option.click();
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Type into the selectable's search box to filter the options. Throws if the
|
|
75
|
+
* selectable is not searchable (no search box rendered).
|
|
76
|
+
*/
|
|
77
|
+
async search(term) {
|
|
78
|
+
// `fill()` auto-waits for the search box; if the selectable is not
|
|
79
|
+
// searchable it surfaces a clear locator-timeout on its own.
|
|
80
|
+
await this.root.locator(EuiSelectableSelectors.SEARCH_SELECTOR).fill(term);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=object.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"object.js","sourceRoot":"","sources":["../../../../../src/playwright/components/selectable/object.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAE,UAAU,EAAoB,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,0CAA0C,CAAC;AAElF;;;;;;;;;GASG;AACH,MAAM,OAAO,mBAAoB,SAAQ,UAAU;IACjD,YAAY,KAAkB,EAAE,QAAgB;QAC9C,KAAK,CAAC,KAAK,EAAE,QAAQ,EAAE,sBAAsB,CAAC,aAAa,CAAC,CAAC;IAC/D,CAAC;IAED;;;;;;OAMG;IACH,IAAW,OAAO;QAChB,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,KAAK,CAAC,YAAY,CAAC,KAAa;QAC9B,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;QAC7D,MAAM,SAAS,GAAG,IAAI,MAAM,CAAC,IAAI,OAAO,eAAe,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI;aACrB,SAAS,CAAC,QAAQ,CAAC;aACnB,MAAM,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,8BAA8B,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC;QACrG,MAAM,CAAC,WAAW,EAAE,YAAY,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACpD,MAAM,CAAC,YAAY,CAAC,cAAc,CAAC;YACnC,MAAM,CAAC,YAAY,CAAC,eAAe,CAAC;SACrC,CAAC,CAAC;QACH,IAAI,WAAW,KAAK,MAAM,IAAI,YAAY,KAAK,MAAM,EAAE,CAAC;YACtD,OAAO;QACT,CAAC;QACD,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,MAAM,CAAC,IAAY;QACvB,mEAAmE;QACnE,6DAA6D;QAC7D,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,sBAAsB,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7E,CAAC;CACF"}
|
package/lib/esm/selectors.d.ts
CHANGED
|
@@ -2,3 +2,4 @@ export { EuiComboBoxSelectors } from './components/combo_box/selectors';
|
|
|
2
2
|
export { EuiDataGridSelectors } from './components/datagrid/selectors';
|
|
3
3
|
export { EuiSuperSelectSelectors } from './components/form/super_select/selectors';
|
|
4
4
|
export { EuiGlobalToastListSelectors } from './components/toast/selectors';
|
|
5
|
+
export { EuiSelectableSelectors } from './components/selectable/selectors';
|
package/lib/esm/selectors.js
CHANGED
|
@@ -9,4 +9,5 @@ export { EuiComboBoxSelectors } from './components/combo_box/selectors';
|
|
|
9
9
|
export { EuiDataGridSelectors } from './components/datagrid/selectors';
|
|
10
10
|
export { EuiSuperSelectSelectors } from './components/form/super_select/selectors';
|
|
11
11
|
export { EuiGlobalToastListSelectors } from './components/toast/selectors';
|
|
12
|
+
export { EuiSelectableSelectors } from './components/selectable/selectors';
|
|
12
13
|
//# sourceMappingURL=selectors.js.map
|
package/lib/esm/selectors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selectors.js","sourceRoot":"","sources":["../../src/selectors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AACnF,OAAO,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC"}
|
|
1
|
+
{"version":3,"file":"selectors.js","sourceRoot":"","sources":["../../src/selectors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AACnF,OAAO,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# EuiSelectableObject
|
|
2
|
+
|
|
3
|
+
Playwright Component Object for [EuiSelectable](https://eui.elastic.co/docs/components/forms/selection/selectable/).
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { EuiSelectableObject } from '@elastic/eui-test-helpers';
|
|
9
|
+
|
|
10
|
+
const selectable = new EuiSelectableObject(page, 'mySelectable');
|
|
11
|
+
await selectable.search('logs');
|
|
12
|
+
await selectable.selectOption('logs-*');
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Set `data-test-subj` on the `<EuiSelectable>` (EUI spreads it onto the `.euiSelectable` root, which the component-type guard verifies). When the selectable renders inside a popover, pass the popover as the `scope` and open or close it from your test. The popover is not this component's concern.
|
|
16
|
+
|
|
17
|
+
## API
|
|
18
|
+
|
|
19
|
+
| Member | Description |
|
|
20
|
+
|---|---|
|
|
21
|
+
| `options` | `Locator` for the rendered options, keeping Playwright auto-retry for count and content assertions. The list is virtualized, so `search()` first rather than scanning a long list. |
|
|
22
|
+
| `selectOption(label)` | Selects the option with the given label. A no-op if it is already checked. |
|
|
23
|
+
| `search(term)` | Types into the search box. Throws if the selectable is not searchable. |
|
|
24
|
+
|
|
25
|
+
`selectOption(label)` matches the label element and suits lists in their default state. It tolerates the screen-reader state text EUI appends (a checked option reads `<label> . Checked option.`) and `append` badges, and it will not match a different option whose label merely starts with the same text. Once you call `search()`, EUI injects highlight markers into the option's label, so a label match no longer resolves. On a searched list, select via the option's own `data-test-subj` or drive it through `options` directly.
|
|
26
|
+
|
|
27
|
+
It also only matches the plain label. A consumer using a custom `renderOption` to add its own content (e.g. a description) inside the option renders that content in the same label element, which breaks the anchored match. Select those options via `options` instead (e.g. `options.filter({ hasText: label })`).
|