@elastic/eui-test-helpers 2.0.0 → 2.1.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.
@@ -1,13 +1,17 @@
1
1
  /**
2
2
  * Stable selectors for
3
3
  * {@link https://eui.elastic.co/docs/components/forms/color-picker/|EuiColorPicker}.
4
- * `*_SELECTOR` values are CSS.
4
+ * `*_SELECTOR` values are CSS, `*_TEST_SUBJ` values are `data-test-subj` names EUI sets itself.
5
5
  */
6
6
  export declare const EuiColorPickerSelectors: {
7
- /** The default text-input anchor. A custom `button` prop has no class of its own. */
7
+ /** Token EUI adds to the anchor's `data-test-subj`, on the default input and on a custom `button` alike. */
8
+ ANCHOR_TEST_SUBJ: string;
9
+ /** The anchor, whether the default text input or a custom `button`. */
8
10
  ANCHOR_SELECTOR: string;
9
11
  /** The popover panel, rendered in a portal and only while open. */
10
12
  PANEL_SELECTOR: string;
11
13
  /** A swatch button inside the panel. */
12
14
  SWATCH_SELECTOR: string;
15
+ /** The hex input inside the panel. Present only when `secondaryInputDisplay` is `top` or `bottom`. */
16
+ SECONDARY_INPUT_SELECTOR: string;
13
17
  };
@@ -15,13 +15,17 @@ exports.EuiColorPickerSelectors = void 0;
15
15
  /**
16
16
  * Stable selectors for
17
17
  * {@link https://eui.elastic.co/docs/components/forms/color-picker/|EuiColorPicker}.
18
- * `*_SELECTOR` values are CSS.
18
+ * `*_SELECTOR` values are CSS, `*_TEST_SUBJ` values are `data-test-subj` names EUI sets itself.
19
19
  */
20
20
  const EuiColorPickerSelectors = exports.EuiColorPickerSelectors = {
21
- /** The default text-input anchor. A custom `button` prop has no class of its own. */
22
- ANCHOR_SELECTOR: '.euiColorPicker__input',
21
+ /** Token EUI adds to the anchor's `data-test-subj`, on the default input and on a custom `button` alike. */
22
+ ANCHOR_TEST_SUBJ: 'euiColorPickerAnchor',
23
+ /** The anchor, whether the default text input or a custom `button`. */
24
+ ANCHOR_SELECTOR: '[data-test-subj~="euiColorPickerAnchor"]',
23
25
  /** The popover panel, rendered in a portal and only while open. */
24
26
  PANEL_SELECTOR: '[data-popover-panel].euiColorPicker__popoverPanel',
25
27
  /** A swatch button inside the panel. */
26
- SWATCH_SELECTOR: '.euiColorPickerSwatch'
28
+ SWATCH_SELECTOR: '.euiColorPickerSwatch',
29
+ /** The hex input inside the panel. Present only when `secondaryInputDisplay` is `top` or `bottom`. */
30
+ SECONDARY_INPUT_SELECTOR: '[data-test-subj^="euiColorPickerInput_"]'
27
31
  };
@@ -13,11 +13,13 @@ exports.BaseObject = void 0;
13
13
  */
14
14
 
15
15
  /**
16
- * Matches one space-separated token in `data-test-subj`, not the whole
17
- * attribute value. `getByTestId` does an exact match and misses components
18
- * like `EuiColorPicker` that add their own token to the consumer's subj.
16
+ * Matches space-separated tokens in `data-test-subj`, not the whole attribute
17
+ * value. `getByTestId` does an exact match and misses components like
18
+ * `EuiColorPicker` that add their own token to the consumer's subj. A
19
+ * `testSubj` with spaces (`colorEditorColorPicker 0`, a Kibana convention) is
20
+ * split so every token must be present, in any order.
19
21
  */
20
- const testSubjSelector = testSubj => `[data-test-subj~="${testSubj.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"]`;
22
+ const testSubjSelector = testSubj => testSubj.trim().split(/\s+/).map(token => `[data-test-subj~="${token.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"]`).join('');
21
23
 
22
24
  /**
23
25
  * Base class for Playwright Component Objects — semantic wrappers around a
@@ -1,12 +1,12 @@
1
- import type { Locator } from '@playwright/test';
1
+ import { type Locator } from '@playwright/test';
2
2
  import { BaseObject, type ObjectScope } from '../../base_object';
3
3
  /**
4
4
  * Playwright Component Object for {@link
5
5
  * https://eui.elastic.co/docs/components/forms/color-picker/ EuiColorPicker}.
6
6
  *
7
- * `testSubj` must be set on `EuiColorPicker` itself. Covers only the default
8
- * text-input anchor, not a custom `button` prop. See the package README for
9
- * what this does not cover.
7
+ * `testSubj` must be set on `EuiColorPicker` itself. `locator` is the anchor:
8
+ * the default text input, or the element passed as the `button` prop. See the
9
+ * package README for what this does not cover.
10
10
  */
11
11
  export declare class EuiColorPickerObject extends BaseObject {
12
12
  constructor(scope: ObjectScope, testSubj: string);
@@ -17,4 +17,25 @@ export declare class EuiColorPickerObject extends BaseObject {
17
17
  get panel(): Locator;
18
18
  /** The swatch buttons inside {@link panel}. */
19
19
  get swatches(): Locator;
20
+ /**
21
+ * Type `color` into the hex input and verify it was accepted. With the
22
+ * default anchor that input is the anchor itself. With a custom `button`
23
+ * the input lives inside the panel, so the picker is opened, filled and
24
+ * closed again. Throws if the panel has no input
25
+ * (`secondaryInputDisplay="none"`).
26
+ */
27
+ setColor(color: string): Promise<void>;
28
+ /**
29
+ * The color shown in the hex input, uppercased. With a custom `button` the
30
+ * picker is opened to read it and closed again.
31
+ */
32
+ getColor(): Promise<string>;
33
+ private isInputAnchor;
34
+ /**
35
+ * Click a custom `button` anchor, which toggles the panel, and wait for the
36
+ * panel to follow. Only used with a custom `button`: the default input
37
+ * anchor opens on click but does not close on a second one.
38
+ */
39
+ private toggle;
40
+ private secondaryInput;
20
41
  }
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.EuiColorPickerObject = void 0;
7
+ var _test = require("@playwright/test");
7
8
  var _base_object = require("../../base_object");
8
9
  var _selectors = require("../../../components/color_picker/selectors");
9
10
  /*
@@ -18,9 +19,9 @@ var _selectors = require("../../../components/color_picker/selectors");
18
19
  * Playwright Component Object for {@link
19
20
  * https://eui.elastic.co/docs/components/forms/color-picker/ EuiColorPicker}.
20
21
  *
21
- * `testSubj` must be set on `EuiColorPicker` itself. Covers only the default
22
- * text-input anchor, not a custom `button` prop. See the package README for
23
- * what this does not cover.
22
+ * `testSubj` must be set on `EuiColorPicker` itself. `locator` is the anchor:
23
+ * the default text input, or the element passed as the `button` prop. See the
24
+ * package README for what this does not cover.
24
25
  */
25
26
  class EuiColorPickerObject extends _base_object.BaseObject {
26
27
  constructor(scope, testSubj) {
@@ -39,5 +40,69 @@ class EuiColorPickerObject extends _base_object.BaseObject {
39
40
  get swatches() {
40
41
  return this.panel.locator(_selectors.EuiColorPickerSelectors.SWATCH_SELECTOR);
41
42
  }
43
+
44
+ /**
45
+ * Type `color` into the hex input and verify it was accepted. With the
46
+ * default anchor that input is the anchor itself. With a custom `button`
47
+ * the input lives inside the panel, so the picker is opened, filled and
48
+ * closed again. Throws if the panel has no input
49
+ * (`secondaryInputDisplay="none"`).
50
+ */
51
+ async setColor(color) {
52
+ // EUI echoes the value back uppercased.
53
+ const expected = color.toUpperCase();
54
+ if (await this.isInputAnchor()) {
55
+ await this.root.fill(color);
56
+ await (0, _test.expect)(this.root).toHaveValue(expected);
57
+ await this.root.blur();
58
+ return;
59
+ }
60
+ await this.toggle();
61
+ const input = await this.secondaryInput();
62
+ await input.fill(color);
63
+ await (0, _test.expect)(input).toHaveValue(expected);
64
+ await this.toggle();
65
+ }
66
+
67
+ /**
68
+ * The color shown in the hex input, uppercased. With a custom `button` the
69
+ * picker is opened to read it and closed again.
70
+ */
71
+ async getColor() {
72
+ if (await this.isInputAnchor()) {
73
+ return this.root.inputValue();
74
+ }
75
+ await this.toggle();
76
+ const value = await (await this.secondaryInput()).inputValue();
77
+ await this.toggle();
78
+ return value;
79
+ }
80
+ async isInputAnchor() {
81
+ return this.root.evaluate(el => el.tagName === 'INPUT');
82
+ }
83
+
84
+ /**
85
+ * Click a custom `button` anchor, which toggles the panel, and wait for the
86
+ * panel to follow. Only used with a custom `button`: the default input
87
+ * anchor opens on click but does not close on a second one.
88
+ */
89
+ async toggle() {
90
+ const wasOpen = (await this.panel.count()) > 0;
91
+ await this.root.click();
92
+ if (wasOpen) {
93
+ await this.panel.waitFor({
94
+ state: 'detached'
95
+ });
96
+ } else {
97
+ await (0, _test.expect)(this.panel).toHaveAttribute('data-popover-open', 'true');
98
+ }
99
+ }
100
+ async secondaryInput() {
101
+ const input = this.panel.locator(_selectors.EuiColorPickerSelectors.SECONDARY_INPUT_SELECTOR);
102
+ if ((await input.count()) === 0) {
103
+ throw new Error(`EuiColorPicker "${this.testSubj}" uses a custom button and its panel has no hex input. ` + `Set secondaryInputDisplay to "top" or "bottom" to read or set its color.`);
104
+ }
105
+ return input;
106
+ }
42
107
  }
43
108
  exports.EuiColorPickerObject = EuiColorPickerObject;
@@ -16,9 +16,11 @@ export declare const selectors: {
16
16
  HEADER_CELL_SELECTOR_PREFIX: string;
17
17
  };
18
18
  readonly colorPicker: {
19
+ ANCHOR_TEST_SUBJ: string;
19
20
  ANCHOR_SELECTOR: string;
20
21
  PANEL_SELECTOR: string;
21
22
  SWATCH_SELECTOR: string;
23
+ SECONDARY_INPUT_SELECTOR: string;
22
24
  };
23
25
  readonly comboBox: {
24
26
  ROOT_SELECTOR: string;
@@ -1,13 +1,17 @@
1
1
  /**
2
2
  * Stable selectors for
3
3
  * {@link https://eui.elastic.co/docs/components/forms/color-picker/|EuiColorPicker}.
4
- * `*_SELECTOR` values are CSS.
4
+ * `*_SELECTOR` values are CSS, `*_TEST_SUBJ` values are `data-test-subj` names EUI sets itself.
5
5
  */
6
6
  export declare const EuiColorPickerSelectors: {
7
- /** The default text-input anchor. A custom `button` prop has no class of its own. */
7
+ /** Token EUI adds to the anchor's `data-test-subj`, on the default input and on a custom `button` alike. */
8
+ ANCHOR_TEST_SUBJ: string;
9
+ /** The anchor, whether the default text input or a custom `button`. */
8
10
  ANCHOR_SELECTOR: string;
9
11
  /** The popover panel, rendered in a portal and only while open. */
10
12
  PANEL_SELECTOR: string;
11
13
  /** A swatch button inside the panel. */
12
14
  SWATCH_SELECTOR: string;
15
+ /** The hex input inside the panel. Present only when `secondaryInputDisplay` is `top` or `bottom`. */
16
+ SECONDARY_INPUT_SELECTOR: string;
13
17
  };
@@ -8,14 +8,18 @@
8
8
  /**
9
9
  * Stable selectors for
10
10
  * {@link https://eui.elastic.co/docs/components/forms/color-picker/|EuiColorPicker}.
11
- * `*_SELECTOR` values are CSS.
11
+ * `*_SELECTOR` values are CSS, `*_TEST_SUBJ` values are `data-test-subj` names EUI sets itself.
12
12
  */
13
13
  export const EuiColorPickerSelectors = {
14
- /** The default text-input anchor. A custom `button` prop has no class of its own. */
15
- ANCHOR_SELECTOR: '.euiColorPicker__input',
14
+ /** Token EUI adds to the anchor's `data-test-subj`, on the default input and on a custom `button` alike. */
15
+ ANCHOR_TEST_SUBJ: 'euiColorPickerAnchor',
16
+ /** The anchor, whether the default text input or a custom `button`. */
17
+ ANCHOR_SELECTOR: '[data-test-subj~="euiColorPickerAnchor"]',
16
18
  /** The popover panel, rendered in a portal and only while open. */
17
19
  PANEL_SELECTOR: '[data-popover-panel].euiColorPicker__popoverPanel',
18
20
  /** A swatch button inside the panel. */
19
21
  SWATCH_SELECTOR: '.euiColorPickerSwatch',
22
+ /** The hex input inside the panel. Present only when `secondaryInputDisplay` is `top` or `bottom`. */
23
+ SECONDARY_INPUT_SELECTOR: '[data-test-subj^="euiColorPickerInput_"]',
20
24
  };
21
25
  //# sourceMappingURL=selectors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"selectors.js","sourceRoot":"","sources":["../../../../src/components/color_picker/selectors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,qFAAqF;IACrF,eAAe,EAAE,wBAAwB;IAEzC,mEAAmE;IACnE,cAAc,EAAE,mDAAmD;IAEnE,wCAAwC;IACxC,eAAe,EAAE,uBAAuB;CACzC,CAAC"}
1
+ {"version":3,"file":"selectors.js","sourceRoot":"","sources":["../../../../src/components/color_picker/selectors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,4GAA4G;IAC5G,gBAAgB,EAAE,sBAAsB;IAExC,uEAAuE;IACvE,eAAe,EAAE,0CAA0C;IAE3D,mEAAmE;IACnE,cAAc,EAAE,mDAAmD;IAEnE,wCAAwC;IACxC,eAAe,EAAE,uBAAuB;IAExC,sGAAsG;IACtG,wBAAwB,EAAE,0CAA0C;CACrE,CAAC"}
@@ -6,11 +6,17 @@
6
6
  * Side Public License, v 1.
7
7
  */
8
8
  /**
9
- * Matches one space-separated token in `data-test-subj`, not the whole
10
- * attribute value. `getByTestId` does an exact match and misses components
11
- * like `EuiColorPicker` that add their own token to the consumer's subj.
9
+ * Matches space-separated tokens in `data-test-subj`, not the whole attribute
10
+ * value. `getByTestId` does an exact match and misses components like
11
+ * `EuiColorPicker` that add their own token to the consumer's subj. A
12
+ * `testSubj` with spaces (`colorEditorColorPicker 0`, a Kibana convention) is
13
+ * split so every token must be present, in any order.
12
14
  */
13
- const testSubjSelector = (testSubj) => `[data-test-subj~="${testSubj.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"]`;
15
+ const testSubjSelector = (testSubj) => testSubj
16
+ .trim()
17
+ .split(/\s+/)
18
+ .map((token) => `[data-test-subj~="${token.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"]`)
19
+ .join('');
14
20
  /**
15
21
  * Base class for Playwright Component Objects — semantic wrappers around a
16
22
  * single root `Locator` resolved from a `data-test-subj` inside the given
@@ -1 +1 @@
1
- {"version":3,"file":"base_object.js","sourceRoot":"","sources":["../../../src/playwright/base_object.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH;;;;GAIG;AACH,MAAM,gBAAgB,GAAG,CAAC,QAAgB,EAAU,EAAE,CACpD,qBAAqB,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC;AAEhF;;;;;;;;;;GAUG;AACH,MAAM,OAAgB,UAAU;IAyB9B,YAAY,KAAkB,EAAE,QAAgB,EAAE,iBAA0B;QAFpE,sBAAiB,GAAG,KAAK,CAAC;QAGhC,IAAI,CAAC,KAAK,GAAG,KAAK,YAAY,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;QACjE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC3D,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;QAE3C,4EAA4E;QAC5E,6EAA6E;QAC7E,2EAA2E;QAC3E,uEAAuE;QACvE,yEAAyE;QACzE,OAAO,IAAI,KAAK,CAAC,IAAI,EAAE;YACrB,GAAG,CAAC,MAAM,EAAE,IAAI;gBACd,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;gBAChD,MAAM,WAAW,GACf,OAAO,KAAK,KAAK,UAAU;oBAC3B,KAAK,CAAC,WAAW,CAAC,IAAI,KAAK,eAAe;oBAC1C,IAAI,KAAK,iBAAiB;oBAC1B,CAAC,CAAC,IAAI,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC;gBAE9B,IAAI,CAAC,WAAW,EAAE,CAAC;oBACjB,OAAO,KAAK,CAAC;gBACf,CAAC;gBAED,OAAO,KAAK,EAAE,GAAG,IAAe,EAAE,EAAE;oBAClC,MAAM,MAAM,CAAC,eAAe,EAAE,CAAC;oBAC/B,OAAO,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;gBAC5C,CAAC,CAAC;YACJ,CAAC;SACF,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED;;;;;;OAMG;IACO,KAAK,CAAC,eAAe;QAC7B,IAAI,IAAI,CAAC,iBAAiB,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACtD,OAAO;QACT,CAAC;QACD,4EAA4E;QAC5E,8EAA8E;QAC9E,yEAAyE;QACzE,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;YACpC,OAAO;QACT,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI;aAC5B,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;aAC/C,KAAK,EAAE,CAAC;QACX,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CACb,6CAA6C,IAAI,CAAC,QAAQ,eAAe,IAAI,CAAC,iBAAiB,KAAK;gBAClG,6EAA6E,CAChF,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAChC,CAAC;CACF"}
1
+ {"version":3,"file":"base_object.js","sourceRoot":"","sources":["../../../src/playwright/base_object.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH;;;;;;GAMG;AACH,MAAM,gBAAgB,GAAG,CAAC,QAAgB,EAAU,EAAE,CACpD,QAAQ;KACL,IAAI,EAAE;KACN,KAAK,CAAC,KAAK,CAAC;KACZ,GAAG,CACF,CAAC,KAAK,EAAE,EAAE,CACR,qBAAqB,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAC7E;KACA,IAAI,CAAC,EAAE,CAAC,CAAC;AAEd;;;;;;;;;;GAUG;AACH,MAAM,OAAgB,UAAU;IAyB9B,YAAY,KAAkB,EAAE,QAAgB,EAAE,iBAA0B;QAFpE,sBAAiB,GAAG,KAAK,CAAC;QAGhC,IAAI,CAAC,KAAK,GAAG,KAAK,YAAY,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;QACjE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC3D,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;QAE3C,4EAA4E;QAC5E,6EAA6E;QAC7E,2EAA2E;QAC3E,uEAAuE;QACvE,yEAAyE;QACzE,OAAO,IAAI,KAAK,CAAC,IAAI,EAAE;YACrB,GAAG,CAAC,MAAM,EAAE,IAAI;gBACd,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;gBAChD,MAAM,WAAW,GACf,OAAO,KAAK,KAAK,UAAU;oBAC3B,KAAK,CAAC,WAAW,CAAC,IAAI,KAAK,eAAe;oBAC1C,IAAI,KAAK,iBAAiB;oBAC1B,CAAC,CAAC,IAAI,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC;gBAE9B,IAAI,CAAC,WAAW,EAAE,CAAC;oBACjB,OAAO,KAAK,CAAC;gBACf,CAAC;gBAED,OAAO,KAAK,EAAE,GAAG,IAAe,EAAE,EAAE;oBAClC,MAAM,MAAM,CAAC,eAAe,EAAE,CAAC;oBAC/B,OAAO,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;gBAC5C,CAAC,CAAC;YACJ,CAAC;SACF,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED;;;;;;OAMG;IACO,KAAK,CAAC,eAAe;QAC7B,IAAI,IAAI,CAAC,iBAAiB,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACtD,OAAO;QACT,CAAC;QACD,4EAA4E;QAC5E,8EAA8E;QAC9E,yEAAyE;QACzE,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;YACpC,OAAO;QACT,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI;aAC5B,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;aAC/C,KAAK,EAAE,CAAC;QACX,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CACb,6CAA6C,IAAI,CAAC,QAAQ,eAAe,IAAI,CAAC,iBAAiB,KAAK;gBAClG,6EAA6E,CAChF,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAChC,CAAC;CACF"}
@@ -1,12 +1,12 @@
1
- import type { Locator } from '@playwright/test';
1
+ import { type Locator } from '@playwright/test';
2
2
  import { BaseObject, type ObjectScope } from '../../base_object';
3
3
  /**
4
4
  * Playwright Component Object for {@link
5
5
  * https://eui.elastic.co/docs/components/forms/color-picker/ EuiColorPicker}.
6
6
  *
7
- * `testSubj` must be set on `EuiColorPicker` itself. Covers only the default
8
- * text-input anchor, not a custom `button` prop. See the package README for
9
- * what this does not cover.
7
+ * `testSubj` must be set on `EuiColorPicker` itself. `locator` is the anchor:
8
+ * the default text input, or the element passed as the `button` prop. See the
9
+ * package README for what this does not cover.
10
10
  */
11
11
  export declare class EuiColorPickerObject extends BaseObject {
12
12
  constructor(scope: ObjectScope, testSubj: string);
@@ -17,4 +17,25 @@ export declare class EuiColorPickerObject extends BaseObject {
17
17
  get panel(): Locator;
18
18
  /** The swatch buttons inside {@link panel}. */
19
19
  get swatches(): Locator;
20
+ /**
21
+ * Type `color` into the hex input and verify it was accepted. With the
22
+ * default anchor that input is the anchor itself. With a custom `button`
23
+ * the input lives inside the panel, so the picker is opened, filled and
24
+ * closed again. Throws if the panel has no input
25
+ * (`secondaryInputDisplay="none"`).
26
+ */
27
+ setColor(color: string): Promise<void>;
28
+ /**
29
+ * The color shown in the hex input, uppercased. With a custom `button` the
30
+ * picker is opened to read it and closed again.
31
+ */
32
+ getColor(): Promise<string>;
33
+ private isInputAnchor;
34
+ /**
35
+ * Click a custom `button` anchor, which toggles the panel, and wait for the
36
+ * panel to follow. Only used with a custom `button`: the default input
37
+ * anchor opens on click but does not close on a second one.
38
+ */
39
+ private toggle;
40
+ private secondaryInput;
20
41
  }
@@ -5,15 +5,16 @@
5
5
  * in compliance with, at your election, the Elastic License 2.0 or the Server
6
6
  * Side Public License, v 1.
7
7
  */
8
+ import { expect } from '@playwright/test';
8
9
  import { BaseObject } from '../../base_object';
9
10
  import { EuiColorPickerSelectors } from '../../../components/color_picker/selectors';
10
11
  /**
11
12
  * Playwright Component Object for {@link
12
13
  * https://eui.elastic.co/docs/components/forms/color-picker/ EuiColorPicker}.
13
14
  *
14
- * `testSubj` must be set on `EuiColorPicker` itself. Covers only the default
15
- * text-input anchor, not a custom `button` prop. See the package README for
16
- * what this does not cover.
15
+ * `testSubj` must be set on `EuiColorPicker` itself. `locator` is the anchor:
16
+ * the default text input, or the element passed as the `button` prop. See the
17
+ * package README for what this does not cover.
17
18
  */
18
19
  export class EuiColorPickerObject extends BaseObject {
19
20
  constructor(scope, testSubj) {
@@ -30,5 +31,66 @@ export class EuiColorPickerObject extends BaseObject {
30
31
  get swatches() {
31
32
  return this.panel.locator(EuiColorPickerSelectors.SWATCH_SELECTOR);
32
33
  }
34
+ /**
35
+ * Type `color` into the hex input and verify it was accepted. With the
36
+ * default anchor that input is the anchor itself. With a custom `button`
37
+ * the input lives inside the panel, so the picker is opened, filled and
38
+ * closed again. Throws if the panel has no input
39
+ * (`secondaryInputDisplay="none"`).
40
+ */
41
+ async setColor(color) {
42
+ // EUI echoes the value back uppercased.
43
+ const expected = color.toUpperCase();
44
+ if (await this.isInputAnchor()) {
45
+ await this.root.fill(color);
46
+ await expect(this.root).toHaveValue(expected);
47
+ await this.root.blur();
48
+ return;
49
+ }
50
+ await this.toggle();
51
+ const input = await this.secondaryInput();
52
+ await input.fill(color);
53
+ await expect(input).toHaveValue(expected);
54
+ await this.toggle();
55
+ }
56
+ /**
57
+ * The color shown in the hex input, uppercased. With a custom `button` the
58
+ * picker is opened to read it and closed again.
59
+ */
60
+ async getColor() {
61
+ if (await this.isInputAnchor()) {
62
+ return this.root.inputValue();
63
+ }
64
+ await this.toggle();
65
+ const value = await (await this.secondaryInput()).inputValue();
66
+ await this.toggle();
67
+ return value;
68
+ }
69
+ async isInputAnchor() {
70
+ return this.root.evaluate((el) => el.tagName === 'INPUT');
71
+ }
72
+ /**
73
+ * Click a custom `button` anchor, which toggles the panel, and wait for the
74
+ * panel to follow. Only used with a custom `button`: the default input
75
+ * anchor opens on click but does not close on a second one.
76
+ */
77
+ async toggle() {
78
+ const wasOpen = (await this.panel.count()) > 0;
79
+ await this.root.click();
80
+ if (wasOpen) {
81
+ await this.panel.waitFor({ state: 'detached' });
82
+ }
83
+ else {
84
+ await expect(this.panel).toHaveAttribute('data-popover-open', 'true');
85
+ }
86
+ }
87
+ async secondaryInput() {
88
+ const input = this.panel.locator(EuiColorPickerSelectors.SECONDARY_INPUT_SELECTOR);
89
+ if ((await input.count()) === 0) {
90
+ throw new Error(`EuiColorPicker "${this.testSubj}" uses a custom button and its panel has no hex input. ` +
91
+ `Set secondaryInputDisplay to "top" or "bottom" to read or set its color.`);
92
+ }
93
+ return input;
94
+ }
33
95
  }
34
96
  //# sourceMappingURL=object.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"object.js","sourceRoot":"","sources":["../../../../../src/playwright/components/color_picker/object.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAE,UAAU,EAAoB,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,4CAA4C,CAAC;AAErF;;;;;;;GAOG;AACH,MAAM,OAAO,oBAAqB,SAAQ,UAAU;IAClD,YAAY,KAAkB,EAAE,QAAgB;QAC9C,KAAK,CAAC,KAAK,EAAE,QAAQ,EAAE,uBAAuB,CAAC,eAAe,CAAC,CAAC;IAClE,CAAC;IAED;;;OAGG;IACH,IAAW,KAAK;QACd,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,uBAAuB,CAAC,cAAc,CAAC,CAAC;IAC1E,CAAC;IAED,+CAA+C;IAC/C,IAAW,QAAQ;QACjB,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,uBAAuB,CAAC,eAAe,CAAC,CAAC;IACrE,CAAC;CACF"}
1
+ {"version":3,"file":"object.js","sourceRoot":"","sources":["../../../../../src/playwright/components/color_picker/object.ts"],"names":[],"mappings":"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"}
@@ -16,9 +16,11 @@ export declare const selectors: {
16
16
  HEADER_CELL_SELECTOR_PREFIX: string;
17
17
  };
18
18
  readonly colorPicker: {
19
+ ANCHOR_TEST_SUBJ: string;
19
20
  ANCHOR_SELECTOR: string;
20
21
  PANEL_SELECTOR: string;
21
22
  SWATCH_SELECTOR: string;
23
+ SECONDARY_INPUT_SELECTOR: string;
22
24
  };
23
25
  readonly comboBox: {
24
26
  ROOT_SELECTOR: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elastic/eui-test-helpers",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "A library of EUI test helpers for RTL, Cypress and Scout",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "repository": {
@@ -8,23 +8,25 @@ Playwright Component Object for [EuiColorPicker](https://eui.elastic.co/docs/com
8
8
  import { EuiColorPickerObject } from '@elastic/eui-test-helpers';
9
9
 
10
10
  const colorPicker = new EuiColorPickerObject(page, 'myColorPicker');
11
- await colorPicker.locator.click();
12
- await colorPicker.swatches.first().click();
11
+ await colorPicker.setColor('#ff0000');
12
+ expect(await colorPicker.getColor()).toBe('#FF0000');
13
13
  ```
14
14
 
15
15
  Set `data-test-subj` on `EuiColorPicker` itself. `EuiColorPicker` renders it on its anchor as `euiColorPickerAnchor <yourSubj>`, a compound value the shared root lookup matches by token. Without that, `getByTestId` on your own subj finds nothing.
16
16
 
17
+ `locator` is the anchor: the default text input, or the element you passed as the `button` prop.
18
+
17
19
  ## API
18
20
 
19
21
  | Member | Description |
20
22
  |---|---|
23
+ | `setColor(color)` | Type `color` into the hex input and verify it was accepted. With the default anchor that input is the anchor itself. With a custom `button` the input is inside the panel, so the picker is opened, filled and closed again. Throws if the panel has no input (`secondaryInputDisplay="none"`). |
24
+ | `getColor()` | The color shown in the hex input, uppercased. With a custom `button` the picker is opened to read it and closed again. |
21
25
  | `panel` | `Locator` for the popover panel. Rendered in a portal, so it is found on the page, not under the anchor. Resolves to zero elements while closed, and gets `data-popover-open="true"` once open. |
22
26
  | `swatches` | `Locator` for the swatch buttons inside `panel`. |
23
27
 
24
- `locator` is the anchor, a plain text input. Click it to open the picker, and use Playwright's own `inputValue()`/`fill()` to read or set the color.
25
-
26
28
  ## Deliberately out of scope
27
29
 
28
- - **A custom `button` prop**: only the default text-input anchor has a class the component-type guard can rely on. A custom button has none, so it is not supported.
29
30
  - **`open()`/`close()` methods**: `EuiPopover` only sets `aria-expanded`/`aria-controls` on button-like toggles, and the default anchor is an input, so the signal `EuiPopoverObject` relies on is missing. Click `locator` and assert on `panel` instead.
31
+ - **`display="inline"`**: there is no anchor and no popover, the picker renders in place. Use plain Playwright locators.
30
32
  - **Several pickers open at once**: `panel` is found by class on the page, so two open pickers would both match. No consumer has needed this.