@redhat-developer/page-objects 1.13.0 → 1.14.1

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.
@@ -17,7 +17,7 @@
17
17
  import { WebElement, WebDriver, Locator } from 'selenium-webdriver';
18
18
  import { Locators } from '../locators/locators';
19
19
  /**
20
- * Default wrapper for webelement
20
+ * Default wrapper for webElement
21
21
  */
22
22
  export declare abstract class AbstractElement extends WebElement {
23
23
  static readonly ctlKey: string;
@@ -30,7 +30,7 @@ export declare abstract class AbstractElement extends WebElement {
30
30
  protected enclosingItem: WebElement;
31
31
  /**
32
32
  * Constructs a new element from a Locator or an existing WebElement
33
- * @param base WebDriver compatible Locator for the given element or a reference to an existing WeBelement
33
+ * @param base WebDriver compatible Locator for the given element or a reference to an existing WebElement
34
34
  * @param enclosingItem Locator or a WebElement reference to an element containing the element being constructed
35
35
  * this will be used to narrow down the search for the underlying DOM element
36
36
  */
@@ -48,4 +48,6 @@ export declare abstract class AbstractElement extends WebElement {
48
48
  */
49
49
  getEnclosingElement(): WebElement;
50
50
  static init(locators: Locators, driver: WebDriver, browser: string, version: string): void;
51
+ withRecovery<T>(fn: (self: this) => Promise<T>): Promise<T>;
52
+ protected reinitialize(): Promise<this>;
51
53
  }
@@ -19,7 +19,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
19
19
  exports.AbstractElement = void 0;
20
20
  const selenium_webdriver_1 = require("selenium-webdriver");
21
21
  /**
22
- * Default wrapper for webelement
22
+ * Default wrapper for webElement
23
23
  */
24
24
  class AbstractElement extends selenium_webdriver_1.WebElement {
25
25
  static ctlKey = process.platform === 'darwin' ? selenium_webdriver_1.Key.COMMAND : selenium_webdriver_1.Key.CONTROL;
@@ -29,7 +29,7 @@ class AbstractElement extends selenium_webdriver_1.WebElement {
29
29
  enclosingItem;
30
30
  /**
31
31
  * Constructs a new element from a Locator or an existing WebElement
32
- * @param base WebDriver compatible Locator for the given element or a reference to an existing WeBelement
32
+ * @param base WebDriver compatible Locator for the given element or a reference to an existing WebElement
33
33
  * @param enclosingItem Locator or a WebElement reference to an element containing the element being constructed
34
34
  * this will be used to narrow down the search for the underlying DOM element
35
35
  */
@@ -80,6 +80,24 @@ class AbstractElement extends selenium_webdriver_1.WebElement {
80
80
  AbstractElement.driver = driver;
81
81
  AbstractElement.versionInfo = { version: version, browser: browser };
82
82
  }
83
+ async withRecovery(fn) {
84
+ try {
85
+ return await fn(this);
86
+ }
87
+ catch (err) {
88
+ if (err.name === 'StaleElementReferenceError' ||
89
+ err.name === 'ElementNotInteractableError' ||
90
+ /element.*(detached|not interactable)/i.test(err.message)) {
91
+ const reinit = await this.reinitialize();
92
+ return await fn(reinit);
93
+ }
94
+ throw err;
95
+ }
96
+ }
97
+ async reinitialize() {
98
+ // Implement generic fallback if possible — otherwise force override in subclasses
99
+ throw new Error(`reinitialize() not implemented in ${this.constructor.name}`);
100
+ }
83
101
  }
84
102
  exports.AbstractElement = AbstractElement;
85
103
  //# sourceMappingURL=AbstractElement.js.map
@@ -23,12 +23,14 @@ const selenium_webdriver_1 = require("selenium-webdriver");
23
23
  class ActionButtonElementDropdown extends AbstractElement_1.AbstractElement {
24
24
  async open() {
25
25
  await this.click();
26
+ await this.getDriver().sleep(500);
26
27
  const shadowRootHost = await this.enclosingItem.findElements(ActionButtonElementDropdown.locators.ContextMenu.shadowRootHost);
27
28
  const actions = this.getDriver().actions();
28
29
  await actions.clear();
29
30
  if (shadowRootHost.length > 0) {
30
31
  if ((await this.getAttribute('aria-expanded')) !== 'true') {
31
32
  await this.click();
33
+ await this.getDriver().sleep(500);
32
34
  }
33
35
  const shadowRoot = await shadowRootHost[0].getShadowRoot();
34
36
  return new ContextMenu_1.ContextMenu(await shadowRoot.findElement(selenium_webdriver_1.By.className('monaco-menu-container'))).wait();
@@ -50,7 +50,7 @@ class ChannelView extends ElementWithContextMenu_1.ElementWithContextMenu {
50
50
  throw Error(`DEPRECATED METHOD! The 'ChannelView.getCurrentChannel' method is broken! Read more information in 'Known Issues > Limitations in testing with VS Code 1.87+' - https://github.com/microsoft/vscode/issues/206897.`);
51
51
  }
52
52
  const combo = await this.enclosingItem.findElement(ChannelView.locators.BottomBarViews.channelCombo);
53
- return await combo.getAttribute('title');
53
+ return await combo.getAttribute(ChannelView.locators.OutputView.currentChannelAttribute);
54
54
  }
55
55
  /**
56
56
  * Select a channel using the selector combo
@@ -72,25 +72,27 @@ class TextView extends ChannelView {
72
72
  * @returns Promise resolving to the view's text
73
73
  */
74
74
  async getText() {
75
- const clipboard = (await import('clipboardy')).default;
76
- let originalClipboard = '';
77
- try {
78
- originalClipboard = clipboard.readSync();
79
- }
80
- catch (error) {
81
- // workaround issue https://github.com/redhat-developer/vscode-extension-tester/issues/835
82
- // do not fail if clipboard is empty
83
- }
84
- const textarea = await this.findElement(ChannelView.locators.BottomBarViews.textArea);
85
- await textarea.sendKeys(selenium_webdriver_1.Key.chord(TextView.ctlKey, 'a'));
86
- await textarea.sendKeys(selenium_webdriver_1.Key.chord(TextView.ctlKey, 'c'));
87
- const text = clipboard.readSync();
88
- // workaround as we are getting "element click intercepted" during the send keys actions.
89
- // await textarea.click();
90
- if (originalClipboard.length > 0) {
91
- clipboard.writeSync(originalClipboard);
92
- }
93
- return text;
75
+ return this.withRecovery(async (self) => {
76
+ const clipboard = (await import('clipboardy')).default;
77
+ let originalClipboard = '';
78
+ try {
79
+ originalClipboard = clipboard.readSync();
80
+ }
81
+ catch (error) {
82
+ // workaround issue https://github.com/redhat-developer/vscode-extension-tester/issues/835
83
+ // do not fail if clipboard is empty
84
+ }
85
+ const textarea = await self.findElement(ChannelView.locators.BottomBarViews.textArea);
86
+ await textarea.sendKeys(selenium_webdriver_1.Key.chord(TextView.ctlKey, 'a'));
87
+ await textarea.sendKeys(selenium_webdriver_1.Key.chord(TextView.ctlKey, 'c'));
88
+ const text = clipboard.readSync();
89
+ // workaround as we are getting "element click intercepted" during the send keys actions.
90
+ // await textarea.click();
91
+ if (originalClipboard.length > 0) {
92
+ clipboard.writeSync(originalClipboard);
93
+ }
94
+ return text;
95
+ });
94
96
  }
95
97
  /**
96
98
  * Clear the text in the current channel
@@ -22,6 +22,7 @@ import { ElementWithContextMenu } from '../ElementWithContextMenu';
22
22
  */
23
23
  export declare class OutputView extends TextView {
24
24
  constructor(panel?: BottomBarPanel);
25
+ protected reinitialize(): Promise<this>;
25
26
  /**
26
27
  * Select a channel using the selector combo
27
28
  * @param name name of the channel to open
@@ -34,6 +35,7 @@ export declare class OutputView extends TextView {
34
35
  */
35
36
  export declare class DebugConsoleView extends ElementWithContextMenu {
36
37
  constructor(panel?: BottomBarPanel);
38
+ protected reinitialize(): Promise<this>;
37
39
  /**
38
40
  * Clear the console of all text
39
41
  */
@@ -29,6 +29,11 @@ class OutputView extends AbstractViews_1.TextView {
29
29
  super(OutputView.locators.OutputView.constructor, panel);
30
30
  this.actionsLabel = OutputView.locators.OutputView.actionsLabel;
31
31
  }
32
+ async reinitialize() {
33
+ const panel = this.enclosingItem;
34
+ const view = await panel.openOutputView();
35
+ return view;
36
+ }
32
37
  /**
33
38
  * Select a channel using the selector combo
34
39
  * @param name name of the channel to open
@@ -46,6 +51,11 @@ class DebugConsoleView extends ElementWithContextMenu_1.ElementWithContextMenu {
46
51
  constructor(panel = new __1.BottomBarPanel()) {
47
52
  super(DebugConsoleView.locators.DebugConsoleView.constructor, panel);
48
53
  }
54
+ async reinitialize() {
55
+ const panel = this.enclosingItem;
56
+ const view = await panel.openDebugConsoleView();
57
+ return view;
58
+ }
49
59
  /**
50
60
  * Clear the console of all text
51
61
  */
@@ -58,9 +68,11 @@ class DebugConsoleView extends ElementWithContextMenu_1.ElementWithContextMenu {
58
68
  * @param expression expression in form of a string
59
69
  */
60
70
  async setExpression(expression) {
61
- const textarea = await this.findElement(DebugConsoleView.locators.BottomBarViews.textArea);
62
- await textarea.clear();
63
- await textarea.sendKeys(expression);
71
+ await this.withRecovery(async (self) => {
72
+ const textarea = await self.findElement(DebugConsoleView.locators.BottomBarViews.textArea);
73
+ await textarea.sendKeys(selenium_webdriver_1.Key.chord(DebugConsoleView.ctlKey, 'a'));
74
+ await textarea.sendKeys(expression);
75
+ });
64
76
  }
65
77
  /**
66
78
  * Evaluate an expression:
@@ -70,11 +82,13 @@ class DebugConsoleView extends ElementWithContextMenu_1.ElementWithContextMenu {
70
82
  * @param expression expression to evaluate. To use existing contents of the debug console text area instead, don't define this argument
71
83
  */
72
84
  async evaluateExpression(expression) {
73
- const textarea = await this.findElement(DebugConsoleView.locators.BottomBarViews.textArea);
74
- if (expression) {
75
- await this.setExpression(expression);
76
- }
77
- await textarea.sendKeys(selenium_webdriver_1.Key.ENTER);
85
+ await this.withRecovery(async (self) => {
86
+ const textarea = await self.findElement(DebugConsoleView.locators.BottomBarViews.textArea);
87
+ if (expression) {
88
+ await self.setExpression(expression);
89
+ }
90
+ await textarea.sendKeys(selenium_webdriver_1.Key.ENTER);
91
+ });
78
92
  }
79
93
  /**
80
94
  * Create a content assist page object
@@ -22,6 +22,7 @@ import { WebElement, Locator } from 'selenium-webdriver';
22
22
  */
23
23
  export declare abstract class Editor extends ElementWithContextMenu {
24
24
  constructor(view?: EditorView | EditorGroup, base?: Locator | WebElement);
25
+ protected reinitialize(): Promise<this>;
25
26
  /**
26
27
  * Get title/name of the open editor
27
28
  */
@@ -26,6 +26,16 @@ class Editor extends ElementWithContextMenu_1.ElementWithContextMenu {
26
26
  constructor(view = new __1.EditorView(), base = Editor.locators.Editor.constructor) {
27
27
  super(base, view);
28
28
  }
29
+ async reinitialize() {
30
+ const editorView = this.enclosingItem;
31
+ const title = await this.getTitle();
32
+ const reopened = await editorView.openEditor(title);
33
+ // Check if we got the same type back
34
+ if (!(reopened instanceof this.constructor)) {
35
+ throw new Error(`Reopened editor is not the same type as original.`);
36
+ }
37
+ return reopened;
38
+ }
29
39
  /**
30
40
  * Get title/name of the open editor
31
41
  */
@@ -92,9 +92,10 @@ export declare class EditorView extends AbstractElement {
92
92
  * Get editor action of a select editor group, search by title or predicate
93
93
  * @param predicateOrTitle title or predicate to be used in search process
94
94
  * @param groupIndex zero based index of the editor group (leftmost group has index 0), default 0
95
+ * @param timeout timeout in milliseconds to wait for the action to appear, default 5000
95
96
  * @returns promise resolving to EditorAction object if found, undefined otherwise
96
97
  */
97
- getAction(predicateOrTitle: string | ((action: EditorAction) => boolean | PromiseLike<boolean>), groupIndex?: number): Promise<EditorAction | undefined>;
98
+ getAction(predicateOrTitle: string | ((action: EditorAction) => boolean | PromiseLike<boolean>), groupIndex?: number, timeout?: number): Promise<EditorAction | undefined>;
98
99
  }
99
100
  /**
100
101
  * Page object representing an editor group
@@ -169,11 +169,14 @@ class EditorView extends AbstractElement_1.AbstractElement {
169
169
  * Get editor action of a select editor group, search by title or predicate
170
170
  * @param predicateOrTitle title or predicate to be used in search process
171
171
  * @param groupIndex zero based index of the editor group (leftmost group has index 0), default 0
172
+ * @param timeout timeout in milliseconds to wait for the action to appear, default 5000
172
173
  * @returns promise resolving to EditorAction object if found, undefined otherwise
173
174
  */
174
- async getAction(predicateOrTitle, groupIndex = 0) {
175
- const group = await this.getEditorGroup(groupIndex);
176
- return group.getAction(predicateOrTitle);
175
+ async getAction(predicateOrTitle, groupIndex = 0, timeout = 5000) {
176
+ return this.getDriver().wait(async () => {
177
+ const group = await this.getEditorGroup(groupIndex);
178
+ return group.getAction(predicateOrTitle);
179
+ }, timeout, `Expected action - '${predicateOrTitle}' was not found.`);
177
180
  }
178
181
  }
179
182
  exports.EditorView = EditorView;
@@ -25,6 +25,7 @@ import { EditorView, EditorGroup } from '../..';
25
25
  export declare class SettingsEditor extends Editor {
26
26
  private divider;
27
27
  constructor(view?: EditorView | EditorGroup);
28
+ protected reinitialize(): Promise<this>;
28
29
  /**
29
30
  * Search for a setting with a particular title and category.
30
31
  * Returns an appropriate Setting object if the label is found,
@@ -30,6 +30,14 @@ class SettingsEditor extends Editor_1.Editor {
30
30
  constructor(view = new __1.EditorView()) {
31
31
  super(view);
32
32
  }
33
+ async reinitialize() {
34
+ const reopened = await new __1.Workbench().openSettings();
35
+ // Check if we got the same type back
36
+ if (!(reopened instanceof this.constructor)) {
37
+ throw new Error(`Reopened editor is not the same type as original.`);
38
+ }
39
+ return reopened;
40
+ }
33
41
  /**
34
42
  * Search for a setting with a particular title and category.
35
43
  * Returns an appropriate Setting object if the label is found,
@@ -43,11 +51,13 @@ class SettingsEditor extends Editor_1.Editor {
43
51
  * @returns Promise resolving to a Setting object if found, undefined otherwise
44
52
  */
45
53
  async findSetting(title, ...categories) {
46
- const category = categories.join(this.divider);
47
- const searchBox = await this.findElement(SettingsEditor.locators.Editor.inputArea);
48
- await searchBox.sendKeys(selenium_webdriver_1.Key.chord(SettingsEditor.ctlKey, 'a'));
49
- await searchBox.sendKeys(`${category}>${title}`);
50
- return await this._getSettingItem(title, category);
54
+ return this.withRecovery(async (self) => {
55
+ const category = categories.join(self.divider);
56
+ const searchBox = await self.findElement(SettingsEditor.locators.Editor.inputArea);
57
+ await searchBox.sendKeys(selenium_webdriver_1.Key.chord(SettingsEditor.ctlKey, 'a'));
58
+ await searchBox.sendKeys(`${category}>${title}`);
59
+ return await self._getSettingItem(title, category);
60
+ });
51
61
  }
52
62
  /**
53
63
  * Search for a setting with a precise ID.
@@ -117,7 +117,7 @@ export declare class TextEditor extends Editor {
117
117
  * @returns Selection page object
118
118
  */
119
119
  getSelection(): Promise<Selection | undefined>;
120
- openFindWidget(): Promise<FindWidget>;
120
+ openFindWidget(timeout?: number): Promise<FindWidget>;
121
121
  /**
122
122
  * Add the given text to the given coordinates
123
123
  * @param line number of the line to type into
@@ -274,6 +274,7 @@ export declare class CodeLens extends AbstractElement {
274
274
  */
275
275
  export declare class FindWidget extends AbstractElement {
276
276
  constructor(element: WebElement, editor: TextEditor);
277
+ protected reinitialize(): Promise<this>;
277
278
  /**
278
279
  * Toggle between find and replace mode
279
280
  * @param replace true for replace, false for find
@@ -83,57 +83,61 @@ class TextEditor extends Editor_1.Editor {
83
83
  * @returns Promise resolving to ContentAssist object when opening, void otherwise
84
84
  */
85
85
  async toggleContentAssist(open) {
86
- let isHidden = true;
87
- try {
88
- const assist = await this.findElement(TextEditor.locators.ContentAssist.constructor);
89
- const klass = await assist.getAttribute('class');
90
- const visibility = await assist.getCssValue('visibility');
91
- isHidden = klass.indexOf('visible') < 0 || visibility === 'hidden';
92
- }
93
- catch (err) {
94
- isHidden = true;
95
- }
96
- const inputarea = await this.findElement(TextEditor.locators.Editor.inputArea);
97
- if (open) {
98
- if (isHidden) {
99
- await inputarea.sendKeys(selenium_webdriver_1.Key.chord(selenium_webdriver_1.Key.CONTROL, selenium_webdriver_1.Key.SPACE));
100
- await this.getDriver().wait(selenium_webdriver_1.until.elementLocated(TextEditor.locators.ContentAssist.constructor), 2000);
86
+ return this.withRecovery(async (self) => {
87
+ let isHidden = true;
88
+ try {
89
+ const assist = await self.findElement(TextEditor.locators.ContentAssist.constructor);
90
+ const klass = await assist.getAttribute('class');
91
+ const visibility = await assist.getCssValue('visibility');
92
+ isHidden = klass.indexOf('visible') < 0 || visibility === 'hidden';
101
93
  }
102
- const assist = await new __1.ContentAssist(this).wait();
103
- await this.getDriver().wait(() => {
104
- return assist.isLoaded();
105
- }, 10000);
106
- return assist;
107
- }
108
- else {
109
- if (!isHidden) {
110
- await inputarea.sendKeys(selenium_webdriver_1.Key.ESCAPE);
94
+ catch (err) {
95
+ isHidden = true;
111
96
  }
112
- }
97
+ const inputarea = await self.findElement(TextEditor.locators.Editor.inputArea);
98
+ if (open) {
99
+ if (isHidden) {
100
+ await inputarea.sendKeys(selenium_webdriver_1.Key.chord(selenium_webdriver_1.Key.CONTROL, selenium_webdriver_1.Key.SPACE));
101
+ await self.getDriver().wait(selenium_webdriver_1.until.elementLocated(TextEditor.locators.ContentAssist.constructor), 2000);
102
+ }
103
+ const assist = await new __1.ContentAssist(self).wait();
104
+ await self.getDriver().wait(() => {
105
+ return assist.isLoaded();
106
+ }, 10000);
107
+ return assist;
108
+ }
109
+ else {
110
+ if (!isHidden) {
111
+ await inputarea.sendKeys(selenium_webdriver_1.Key.ESCAPE);
112
+ }
113
+ }
114
+ });
113
115
  }
114
116
  /**
115
117
  * Get all text from the editor
116
118
  * @returns Promise resolving to editor text
117
119
  */
118
120
  async getText() {
119
- const clipboard = (await import('clipboardy')).default;
120
- let originalClipboard = '';
121
- try {
122
- originalClipboard = clipboard.readSync();
123
- }
124
- catch (error) {
125
- // workaround issue https://github.com/redhat-developer/vscode-extension-tester/issues/835
126
- // do not fail if clipboard is empty
127
- }
128
- const inputarea = await this.findElement(TextEditor.locators.Editor.inputArea);
129
- await inputarea.sendKeys(selenium_webdriver_1.Key.chord(TextEditor.ctlKey, 'a'), selenium_webdriver_1.Key.chord(TextEditor.ctlKey, 'c'));
130
- await new Promise((res) => setTimeout(res, 500));
131
- const text = clipboard.readSync();
132
- await inputarea.sendKeys(selenium_webdriver_1.Key.UP);
133
- if (originalClipboard.length > 0) {
134
- clipboard.writeSync(originalClipboard);
135
- }
136
- return text;
121
+ return this.withRecovery(async (self) => {
122
+ const clipboard = (await import('clipboardy')).default;
123
+ let originalClipboard = '';
124
+ try {
125
+ originalClipboard = clipboard.readSync();
126
+ }
127
+ catch (error) {
128
+ // workaround issue https://github.com/redhat-developer/vscode-extension-tester/issues/835
129
+ // do not fail if clipboard is empty
130
+ }
131
+ const inputarea = await self.findElement(TextEditor.locators.Editor.inputArea);
132
+ await inputarea.sendKeys(selenium_webdriver_1.Key.chord(TextEditor.ctlKey, 'a'), selenium_webdriver_1.Key.chord(TextEditor.ctlKey, 'c'));
133
+ await new Promise((res) => setTimeout(res, 500));
134
+ const text = clipboard.readSync();
135
+ await inputarea.sendKeys(selenium_webdriver_1.Key.UP);
136
+ if (originalClipboard.length > 0) {
137
+ clipboard.writeSync(originalClipboard);
138
+ }
139
+ return text;
140
+ });
137
141
  }
138
142
  /**
139
143
  * Replace the contents of the editor with a given text
@@ -166,9 +170,11 @@ class TextEditor extends Editor_1.Editor {
166
170
  * @returns Promise resolving once the text is deleted
167
171
  */
168
172
  async clearText() {
169
- const inputarea = await this.findElement(TextEditor.locators.Editor.inputArea);
170
- await inputarea.sendKeys(selenium_webdriver_1.Key.chord(TextEditor.ctlKey, 'a'));
171
- await inputarea.sendKeys(selenium_webdriver_1.Key.BACK_SPACE);
173
+ return this.withRecovery(async (self) => {
174
+ const input = await self.findElement(TextEditor.locators.Editor.inputArea);
175
+ await input.sendKeys(selenium_webdriver_1.Key.chord(TextEditor.ctlKey, 'a'));
176
+ await input.sendKeys(selenium_webdriver_1.Key.BACK_SPACE);
177
+ });
172
178
  }
173
179
  /**
174
180
  * Get text from a given line
@@ -291,12 +297,12 @@ class TextEditor extends Editor_1.Editor {
291
297
  }
292
298
  return new Selection(selection[0], this);
293
299
  }
294
- async openFindWidget() {
300
+ async openFindWidget(timeout = 2_000) {
295
301
  const actions = this.getDriver().actions();
296
302
  await actions.clear();
297
303
  await actions.keyDown(TextEditor.ctlKey).sendKeys('f').keyUp(TextEditor.ctlKey).perform();
298
- const widget = await this.getDriver().wait(selenium_webdriver_1.until.elementLocated(TextEditor.locators.TextEditor.findWidget), 2000);
299
- await this.getDriver().wait(selenium_webdriver_1.until.elementIsVisible(widget), 2000);
304
+ const widget = await this.getDriver().wait(selenium_webdriver_1.until.elementLocated(TextEditor.locators.TextEditor.findWidget), timeout);
305
+ await this.getDriver().wait(selenium_webdriver_1.until.elementIsVisible(widget), timeout);
300
306
  return new FindWidget(widget, this);
301
307
  }
302
308
  /**
@@ -695,6 +701,11 @@ class FindWidget extends AbstractElement_1.AbstractElement {
695
701
  constructor(element, editor) {
696
702
  super(element, editor);
697
703
  }
704
+ async reinitialize() {
705
+ const editor = this.enclosingItem;
706
+ const widgetElement = await editor.findElement(FindWidget.locators.TextEditor.findWidget);
707
+ return new this.constructor(widgetElement, editor);
708
+ }
698
709
  /**
699
710
  * Toggle between find and replace mode
700
711
  * @param replace true for replace, false for find
@@ -38,7 +38,7 @@ class DebugView extends SideBarView_1.SideBarView {
38
38
  }
39
39
  const action = await this.getTitlePart().findElement(DebugView.locators.DebugView.launchCombo);
40
40
  const combo = await action.findElement(DebugView.locators.DebugView.launchSelect);
41
- return await combo.getAttribute('title');
41
+ return await combo.getAttribute(DebugView.locators.DebugView.launchSelectAttribute);
42
42
  }
43
43
  /**
44
44
  * Get titles of all available launch configurations
@@ -98,6 +98,7 @@ export interface Locators {
98
98
  constructor: By;
99
99
  actionsLabel: string;
100
100
  optionByName: (name: string) => By;
101
+ currentChannelAttribute: string;
101
102
  };
102
103
  WebviewView: {
103
104
  iframe: By;
@@ -445,6 +446,7 @@ export interface Locators {
445
446
  DebugView: {
446
447
  launchCombo: By;
447
448
  launchSelect: By;
449
+ launchSelectAttribute: string;
448
450
  launchOption: By;
449
451
  optionByName: (name: string) => By;
450
452
  startButton: By;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redhat-developer/page-objects",
3
- "version": "1.13.0",
3
+ "version": "1.14.1",
4
4
  "description": "Page Object API implementation for a VS Code editor used by ExTester framework.",
5
5
  "main": "out/index.js",
6
6
  "types": "out/index.d.ts",
@@ -47,5 +47,5 @@
47
47
  "selenium-webdriver": ">=4.6.1",
48
48
  "typescript": ">=4.6.2"
49
49
  },
50
- "gitHead": "4db425755901a5152c4379656b75ab97193c1988"
50
+ "gitHead": "f7c20839e93f93fdfe96e56a53c55b3d2c7fde92"
51
51
  }