@redhat-developer/page-objects 1.17.0 → 1.18.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.
Files changed (36) hide show
  1. package/out/components/AbstractElement.d.ts +77 -1
  2. package/out/components/AbstractElement.js +169 -12
  3. package/out/components/ActionButtonElementDropdown.js +14 -2
  4. package/out/components/activityBar/ViewControl.js +5 -1
  5. package/out/components/bottomBar/Views.js +25 -12
  6. package/out/components/editor/ContentAssist.js +2 -1
  7. package/out/components/editor/EditorView.js +50 -9
  8. package/out/components/editor/ExtensionEditorDetailsSection.js +31 -7
  9. package/out/components/editor/SettingsEditor.js +110 -28
  10. package/out/components/editor/TextEditor.js +120 -25
  11. package/out/components/menu/ContextMenu.js +27 -6
  12. package/out/components/menu/MenuItem.js +14 -1
  13. package/out/components/menu/TitleBar.js +15 -3
  14. package/out/components/sidebar/ViewSection.js +14 -4
  15. package/out/components/sidebar/WelcomeContent.js +10 -2
  16. package/out/components/sidebar/debug/DebugView.js +10 -2
  17. package/out/components/sidebar/extensions/ExtensionsViewSection.js +20 -5
  18. package/out/components/sidebar/scm/NewScmView.js +53 -13
  19. package/out/components/sidebar/scm/ScmView.js +12 -4
  20. package/out/components/sidebar/tree/TreeSection.js +11 -3
  21. package/out/components/sidebar/tree/custom/CustomTreeSection.js +22 -6
  22. package/out/components/sidebar/tree/debug/WatchSection.js +5 -1
  23. package/out/components/sidebar/tree/default/DefaultTreeSection.js +9 -1
  24. package/out/components/workbench/Notification.js +10 -2
  25. package/out/components/workbench/NotificationsCenter.js +11 -3
  26. package/out/components/workbench/Workbench.js +14 -4
  27. package/out/components/workbench/input/Input.js +45 -16
  28. package/out/components/workbench/input/InputBox.js +20 -4
  29. package/out/components/workbench/input/QuickOpenBox.js +11 -3
  30. package/out/errors/ExTesterError.d.ts +112 -0
  31. package/out/errors/ExTesterError.js +201 -0
  32. package/out/index.d.ts +2 -0
  33. package/out/index.js +2 -0
  34. package/out/utils/WaitHelper.d.ts +202 -0
  35. package/out/utils/WaitHelper.js +465 -0
  36. package/package.json +4 -4
@@ -65,7 +65,8 @@ class ExtensionsViewSection extends ViewSection_1.ViewSection {
65
65
  throw err;
66
66
  }
67
67
  }
68
- await this.getDriver().wait(selenium_webdriver_1.until.elementIsNotVisible(progress));
68
+ // Wait for search to complete with a timeout to prevent hanging
69
+ await this.getDriver().wait(selenium_webdriver_1.until.elementIsNotVisible(progress), 30000);
69
70
  const parent = this.enclosingItem;
70
71
  const sectionTitle = this.getSectionForCategory(title);
71
72
  const section = (await parent.getSection(sectionTitle));
@@ -75,8 +76,16 @@ class ExtensionsViewSection extends ViewSection_1.ViewSection {
75
76
  }
76
77
  const extensions = await section.getVisibleItems();
77
78
  for (const extension of extensions) {
78
- if ((await extension.getTitle()) === title) {
79
- return extension;
79
+ try {
80
+ if ((await extension.getTitle()) === title) {
81
+ return extension;
82
+ }
83
+ }
84
+ catch (e) {
85
+ if (e.name === 'StaleElementReferenceError') {
86
+ continue;
87
+ }
88
+ throw e;
80
89
  }
81
90
  }
82
91
  return undefined;
@@ -92,8 +101,14 @@ class ExtensionsViewSection extends ViewSection_1.ViewSection {
92
101
  try {
93
102
  await textField.findElement(ExtensionsViewSection.locators.ExtensionsViewSection.textField);
94
103
  await searchField.sendKeys(selenium_webdriver_1.Key.chord(ExtensionsViewItem_1.ExtensionsViewItem.ctlKey, 'a'), selenium_webdriver_1.Key.BACK_SPACE);
95
- await this.getDriver().wait(selenium_webdriver_1.until.elementIsVisible(progress));
96
- await this.getDriver().wait(selenium_webdriver_1.until.elementIsNotVisible(progress));
104
+ // Add timeouts to prevent indefinite waits
105
+ try {
106
+ await this.getDriver().wait(selenium_webdriver_1.until.elementIsVisible(progress), 2000);
107
+ }
108
+ catch {
109
+ // Progress indicator may not appear for quick operations
110
+ }
111
+ await this.getDriver().wait(selenium_webdriver_1.until.elementIsNotVisible(progress), 10000);
97
112
  }
98
113
  catch (err) {
99
114
  // do nothing, the text field is empty
@@ -70,8 +70,16 @@ class SingleScmProvider extends ScmView_1.ScmProvider {
70
70
  const titlePart = view.getTitlePart();
71
71
  const elements = await titlePart.findElements(ScmView_1.ScmView.locators.ScmView.action);
72
72
  for (const element of elements) {
73
- const title = await element.getAttribute(ScmView_1.ScmView.locators.ScmView.actionLabel);
74
- buttons.push(await new ViewTitlePart_1.TitleActionButton(ScmView_1.ScmView.locators.ScmView.actionConstructor(title), titlePart).wait());
73
+ try {
74
+ const title = await element.getAttribute(ScmView_1.ScmView.locators.ScmView.actionLabel);
75
+ buttons.push(await new ViewTitlePart_1.TitleActionButton(ScmView_1.ScmView.locators.ScmView.actionConstructor(title), titlePart).wait());
76
+ }
77
+ catch (e) {
78
+ if (e.name === 'StaleElementReferenceError') {
79
+ continue;
80
+ }
81
+ throw e;
82
+ }
75
83
  }
76
84
  names = await Promise.all(buttons.map(async (button) => button.getTitle()));
77
85
  }
@@ -108,9 +116,17 @@ class SingleScmProvider extends ScmView_1.ScmProvider {
108
116
  const depth = +(await header.getAttribute('aria-level')) + 1;
109
117
  const items = await this.findElements(NewScmView.locators.ScmView.itemLevel(depth));
110
118
  for (const item of items) {
111
- const index = +(await item.getAttribute('data-index'));
112
- if (index > startIndex && index <= startIndex + count) {
113
- elements.push(item);
119
+ try {
120
+ const index = +(await item.getAttribute('data-index'));
121
+ if (index > startIndex && index <= startIndex + count) {
122
+ elements.push(item);
123
+ }
124
+ }
125
+ catch (e) {
126
+ if (e.name === 'StaleElementReferenceError') {
127
+ continue;
128
+ }
129
+ throw e;
114
130
  }
115
131
  }
116
132
  }
@@ -151,8 +167,16 @@ class MultiScmProvider extends ScmView_1.ScmProvider {
151
167
  const headers = await this.enclosingItem.findElements(locator);
152
168
  let header;
153
169
  for (const item of headers) {
154
- if (+(await item.getAttribute('data-index')) > index) {
155
- header = item;
170
+ try {
171
+ if (+(await item.getAttribute('data-index')) > index) {
172
+ header = item;
173
+ }
174
+ }
175
+ catch (e) {
176
+ if (e.name === 'StaleElementReferenceError') {
177
+ continue;
178
+ }
179
+ throw e;
156
180
  }
157
181
  }
158
182
  if (!header) {
@@ -162,9 +186,17 @@ class MultiScmProvider extends ScmView_1.ScmProvider {
162
186
  const depth = +(await header.getAttribute('aria-level')) + 1;
163
187
  const items = await this.enclosingItem.findElements(NewScmView.locators.ScmView.itemLevel(depth));
164
188
  for (const item of items) {
165
- const index = +(await item.getAttribute('data-index'));
166
- if (index > startIndex && index <= startIndex + count) {
167
- elements.push(item);
189
+ try {
190
+ const index = +(await item.getAttribute('data-index'));
191
+ if (index > startIndex && index <= startIndex + count) {
192
+ elements.push(item);
193
+ }
194
+ }
195
+ catch (e) {
196
+ if (e.name === 'StaleElementReferenceError') {
197
+ continue;
198
+ }
199
+ throw e;
168
200
  }
169
201
  }
170
202
  }
@@ -175,9 +207,17 @@ class MultiScmProvider extends ScmView_1.ScmProvider {
175
207
  const rows = await this.enclosingItem.findElements(locator);
176
208
  const index = +(await this.getAttribute('data-index'));
177
209
  for (const row of rows) {
178
- if (+(await row.getAttribute('data-index')) > index) {
179
- const count = await rows[0].findElement(ScmView_1.ScmChange.locators.ScmView.changeCount);
180
- return +(await count.getText());
210
+ try {
211
+ if (+(await row.getAttribute('data-index')) > index) {
212
+ const count = await rows[0].findElement(ScmView_1.ScmChange.locators.ScmView.changeCount);
213
+ return +(await count.getText());
214
+ }
215
+ }
216
+ catch (e) {
217
+ if (e.name === 'StaleElementReferenceError') {
218
+ continue;
219
+ }
220
+ throw e;
181
221
  }
182
222
  }
183
223
  return 0;
@@ -145,10 +145,18 @@ class ScmProvider extends AbstractElement_1.AbstractElement {
145
145
  let i = -1;
146
146
  elements = await this.findElements(ScmProvider.locators.ScmView.changeItem);
147
147
  for (const [index, item] of elements.entries()) {
148
- const name = await item.findElement(ScmProvider.locators.ScmView.changeName);
149
- if ((await name.getText()) === label) {
150
- i = index + 1;
151
- break;
148
+ try {
149
+ const name = await item.findElement(ScmProvider.locators.ScmView.changeName);
150
+ if ((await name.getText()) === label) {
151
+ i = index + 1;
152
+ break;
153
+ }
154
+ }
155
+ catch (e) {
156
+ if (e.name === 'StaleElementReferenceError') {
157
+ continue;
158
+ }
159
+ throw e;
152
160
  }
153
161
  }
154
162
  if (i < 0) {
@@ -57,9 +57,17 @@ class TreeSection extends ViewSection_1.ViewSection {
57
57
  if (i + 1 < path.length) {
58
58
  currentItem = undefined;
59
59
  for (const item of items) {
60
- if ((await item.getLabel()) === path[i + 1]) {
61
- currentItem = item;
62
- break;
60
+ try {
61
+ if ((await item.getLabel()) === path[i + 1]) {
62
+ currentItem = item;
63
+ break;
64
+ }
65
+ }
66
+ catch (e) {
67
+ if (e.name === 'StaleElementReferenceError') {
68
+ continue;
69
+ }
70
+ throw e;
63
71
  }
64
72
  }
65
73
  }
@@ -42,8 +42,16 @@ class GenericCustomTreeSection extends TreeSection_1.TreeSection {
42
42
  const container = await this.getContainer();
43
43
  const elements = await container.findElements(CustomTreeSection.locators.CustomTreeSection.itemRow);
44
44
  for (const element of elements) {
45
- if (await element.isDisplayed()) {
46
- items.push(new this.itemConstructor(element, this));
45
+ try {
46
+ if (await element.isDisplayed()) {
47
+ items.push(new this.itemConstructor(element, this));
48
+ }
49
+ }
50
+ catch (e) {
51
+ if (e.name === 'StaleElementReferenceError') {
52
+ continue;
53
+ }
54
+ throw e;
47
55
  }
48
56
  }
49
57
  return items;
@@ -52,11 +60,19 @@ class GenericCustomTreeSection extends TreeSection_1.TreeSection {
52
60
  const predicate = typeof labelOrPredicate === 'string' ? async (el) => (await el.getLabel()) === labelOrPredicate : labelOrPredicate;
53
61
  const elements = await this.getVisibleItems();
54
62
  for (const element of elements) {
55
- if (await predicate(element)) {
56
- const level = +(await element.getAttribute(CustomTreeSection.locators.ViewSection.level));
57
- if (maxLevel < 1 || level <= maxLevel) {
58
- return element;
63
+ try {
64
+ if (await predicate(element)) {
65
+ const level = +(await element.getAttribute(CustomTreeSection.locators.ViewSection.level));
66
+ if (maxLevel < 1 || level <= maxLevel) {
67
+ return element;
68
+ }
69
+ }
70
+ }
71
+ catch (e) {
72
+ if (e.name === 'StaleElementReferenceError') {
73
+ continue;
59
74
  }
75
+ throw e;
60
76
  }
61
77
  }
62
78
  return undefined;
@@ -30,7 +30,11 @@ class WatchSection extends CustomTreeSection_1.GenericCustomTreeSection {
30
30
  */
31
31
  async addItem(name) {
32
32
  await (await this.getAction(WatchSection.locators.WatchSection.addExpression))?.click();
33
- await new Promise((res) => setTimeout(res, 1000));
33
+ // Wait for input field to appear
34
+ await this.getWaitHelper().forCondition(async () => {
35
+ const inputs = await this.findElements(WatchSection.locators.WatchSection.input);
36
+ return inputs.length > 0;
37
+ }, { timeout: 3000, pollInterval: 100 });
34
38
  const textInput = await this.findElement(WatchSection.locators.WatchSection.input);
35
39
  await textInput.clear();
36
40
  await textInput.sendKeys(name + selenium_webdriver_1.Key.ENTER);
@@ -28,7 +28,15 @@ class DefaultTreeSection extends TreeSection_1.TreeSection {
28
28
  const items = [];
29
29
  const elements = await this.findElements(DefaultTreeSection.locators.DefaultTreeSection.itemRow);
30
30
  for (const element of elements) {
31
- items.push(await new DefaultTreeItem_1.DefaultTreeItem(element, this).wait());
31
+ try {
32
+ items.push(await new DefaultTreeItem_1.DefaultTreeItem(element, this).wait());
33
+ }
34
+ catch (e) {
35
+ if (e.name === 'StaleElementReferenceError') {
36
+ continue;
37
+ }
38
+ throw e;
39
+ }
32
40
  }
33
41
  return items;
34
42
  }
@@ -97,8 +97,16 @@ class Notification extends ElementWithContextMenu_1.ElementWithContextMenu {
97
97
  const buttons = [];
98
98
  const elements = await this.findElement(Notification.locators.Notification.actions).findElements(Notification.locators.Notification.action);
99
99
  for (const button of elements) {
100
- const title = await Notification.locators.Notification.actionLabel.value(button);
101
- buttons.push(await new NotificationButton(Notification.locators.Notification.buttonConstructor(title), this).wait());
100
+ try {
101
+ const title = await Notification.locators.Notification.actionLabel.value(button);
102
+ buttons.push(await new NotificationButton(Notification.locators.Notification.buttonConstructor(title), this).wait());
103
+ }
104
+ catch (e) {
105
+ if (e.name === 'StaleElementReferenceError') {
106
+ continue;
107
+ }
108
+ throw e;
109
+ }
102
110
  }
103
111
  return buttons;
104
112
  }
@@ -61,9 +61,17 @@ class NotificationsCenter extends AbstractElement_1.AbstractElement {
61
61
  const notifications = [];
62
62
  const elements = await this.findElements(NotificationsCenter.locators.NotificationsCenter.row);
63
63
  for (const element of elements) {
64
- const not = new Notification_1.CenterNotification(element);
65
- if (type === Notification_1.NotificationType.Any || (await not.getType()) === type) {
66
- notifications.push(await not.wait());
64
+ try {
65
+ const not = new Notification_1.CenterNotification(element);
66
+ if (type === Notification_1.NotificationType.Any || (await not.getType()) === type) {
67
+ notifications.push(await not.wait());
68
+ }
69
+ }
70
+ catch (e) {
71
+ if (e.name === 'StaleElementReferenceError') {
72
+ continue;
73
+ }
74
+ throw e;
67
75
  }
68
76
  }
69
77
  return notifications;
@@ -88,7 +88,15 @@ class Workbench extends AbstractElement_1.AbstractElement {
88
88
  }
89
89
  const elements = await container.findElements(Workbench.locators.Workbench.notificationItem);
90
90
  for (const element of elements) {
91
- notifications.push(await new Notification_1.StandaloneNotification(element).wait());
91
+ try {
92
+ notifications.push(await new Notification_1.StandaloneNotification(element).wait());
93
+ }
94
+ catch (e) {
95
+ if (e.name === 'StaleElementReferenceError') {
96
+ continue;
97
+ }
98
+ throw e;
99
+ }
92
100
  }
93
101
  return notifications;
94
102
  }
@@ -105,11 +113,13 @@ class Workbench extends AbstractElement_1.AbstractElement {
105
113
  * @returns promise that resolves to a SettingsEditor instance
106
114
  */
107
115
  async openSettings() {
108
- await this.executeCommand('open user settings');
116
+ await this.executeCommand('Preferences: Open User Settings');
109
117
  await new EditorView_1.EditorView().openEditor('Settings');
110
118
  await Workbench.driver.wait(selenium_webdriver_1.until.elementLocated(Workbench.locators.Editor.constructor));
111
- await new Promise((res) => setTimeout(res, 500));
112
- return new SettingsEditor_1.SettingsEditor();
119
+ // Wait for settings editor to fully load
120
+ const editor = new SettingsEditor_1.SettingsEditor();
121
+ await this.getWaitHelper().forStable(editor, { timeout: 2000 });
122
+ return editor;
113
123
  }
114
124
  /**
115
125
  * Open the VS Code command line prompt
@@ -50,7 +50,12 @@ class Input extends AbstractElement_1.AbstractElement {
50
50
  }
51
51
  const input = await this.findElement(Input.locators.Input.inputBox).findElement(Input.locators.Input.input);
52
52
  await this.clear();
53
- await new Promise((res) => setTimeout(res, 200));
53
+ // Wait for clear operation to complete
54
+ await this.getWaitHelper()
55
+ .forCondition(async () => (await this.getText()).length === 0, { timeout: 1000, pollInterval: 50 })
56
+ .catch(() => {
57
+ /* Text may not be empty if clear didn't work fully */
58
+ });
54
59
  if ((await this.getText()).length > 0) {
55
60
  await input.sendKeys(selenium_webdriver_1.Key.END, selenium_webdriver_1.Key.chord(selenium_webdriver_1.Key.SHIFT, selenium_webdriver_1.Key.HOME));
56
61
  }
@@ -152,21 +157,29 @@ class Input extends AbstractElement_1.AbstractElement {
152
157
  while (!endReached) {
153
158
  const picks = await this.getQuickPicks();
154
159
  for (const pick of picks) {
155
- const lastRow = await this.findElements(Input.locators.DefaultTreeSection.lastRow);
156
- if (lastRow.length > 0) {
157
- endReached = true;
158
- }
159
- else if ((await pick.getAttribute('aria-posinset')) === (await pick.getAttribute('aria-setsize'))) {
160
- endReached = true;
161
- }
162
- if (typeof indexOrText === 'string') {
163
- const text = await pick.getLabel();
164
- if (text.indexOf(indexOrText) > -1) {
160
+ try {
161
+ const lastRow = await this.findElements(Input.locators.DefaultTreeSection.lastRow);
162
+ if (lastRow.length > 0) {
163
+ endReached = true;
164
+ }
165
+ else if ((await pick.getAttribute('aria-posinset')) === (await pick.getAttribute('aria-setsize'))) {
166
+ endReached = true;
167
+ }
168
+ if (typeof indexOrText === 'string') {
169
+ const text = await pick.getLabel();
170
+ if (text.indexOf(indexOrText) > -1) {
171
+ return pick;
172
+ }
173
+ }
174
+ else if (indexOrText === pick.getIndex()) {
165
175
  return pick;
166
176
  }
167
177
  }
168
- else if (indexOrText === pick.getIndex()) {
169
- return pick;
178
+ catch (e) {
179
+ if (e.name === 'StaleElementReferenceError') {
180
+ continue;
181
+ }
182
+ throw e;
170
183
  }
171
184
  }
172
185
  if (!endReached) {
@@ -281,7 +294,15 @@ class QuickPickItem extends AbstractElement_1.AbstractElement {
281
294
  const actions = [];
282
295
  const elements = await this.findElements(Input.locators.Input.button);
283
296
  for (const element of elements) {
284
- actions.push(await new QuickInputAction(element, this).wait());
297
+ try {
298
+ actions.push(await new QuickInputAction(element, this).wait());
299
+ }
300
+ catch (e) {
301
+ if (e.name === 'StaleElementReferenceError') {
302
+ continue;
303
+ }
304
+ throw e;
305
+ }
285
306
  }
286
307
  return actions;
287
308
  }
@@ -293,8 +314,16 @@ class QuickPickItem extends AbstractElement_1.AbstractElement {
293
314
  async getAction(label) {
294
315
  const actions = await this.getActions();
295
316
  for (const action of actions) {
296
- if ((await action.getLabel()) === label) {
297
- return action;
317
+ try {
318
+ if ((await action.getLabel()) === label) {
319
+ return action;
320
+ }
321
+ }
322
+ catch (e) {
323
+ if (e.name === 'StaleElementReferenceError') {
324
+ continue;
325
+ }
326
+ throw e;
298
327
  }
299
328
  }
300
329
  }
@@ -51,8 +51,16 @@ class InputBox extends __1.Input {
51
51
  .findElement(InputBox.locators.InputBox.rows)
52
52
  .findElements(InputBox.locators.InputBox.row);
53
53
  for (const element of elements) {
54
- if (await element.isDisplayed()) {
55
- picks.push(await new __1.QuickPickItem(+(await element.getAttribute('data-index')), this).wait());
54
+ try {
55
+ if (await element.isDisplayed()) {
56
+ picks.push(await new __1.QuickPickItem(+(await element.getAttribute('data-index')), this).wait());
57
+ }
58
+ }
59
+ catch (e) {
60
+ if (e.name === 'StaleElementReferenceError') {
61
+ continue;
62
+ }
63
+ throw e;
56
64
  }
57
65
  }
58
66
  return picks;
@@ -63,8 +71,16 @@ class InputBox extends __1.Input {
63
71
  .findElement(InputBox.locators.InputBox.rows)
64
72
  .findElements(InputBox.locators.InputBox.row);
65
73
  for (const element of elements) {
66
- if (await element.isDisplayed()) {
67
- picks.push(await new __1.QuickPickItem(+(await element.getAttribute('data-index')), this, true).wait());
74
+ try {
75
+ if (await element.isDisplayed()) {
76
+ picks.push(await new __1.QuickPickItem(+(await element.getAttribute('data-index')), this, true).wait());
77
+ }
78
+ }
79
+ catch (e) {
80
+ if (e.name === 'StaleElementReferenceError') {
81
+ continue;
82
+ }
83
+ throw e;
68
84
  }
69
85
  }
70
86
  return picks;
@@ -44,9 +44,17 @@ class QuickOpenBox extends __1.Input {
44
44
  const tree = await this.getDriver().wait(selenium_webdriver_1.until.elementLocated(QuickOpenBox.locators.QuickOpenBox.quickList), 1000);
45
45
  const elements = await tree.findElements(QuickOpenBox.locators.QuickOpenBox.row);
46
46
  for (const element of elements) {
47
- const index = +(await element.getAttribute('aria-posinset'));
48
- if (await element.isDisplayed()) {
49
- picks.push(await new __1.QuickPickItem(index, this).wait());
47
+ try {
48
+ const index = +(await element.getAttribute('aria-posinset'));
49
+ if (await element.isDisplayed()) {
50
+ picks.push(await new __1.QuickPickItem(index, this).wait());
51
+ }
52
+ }
53
+ catch (e) {
54
+ if (e.name === 'StaleElementReferenceError') {
55
+ continue;
56
+ }
57
+ throw e;
50
58
  }
51
59
  }
52
60
  return picks;
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Licensed to the Apache Software Foundation (ASF) under one or more
3
+ * contributor license agreements. See the NOTICE file distributed with
4
+ * this work for additional information regarding copyright ownership.
5
+ * The ASF licenses this file to You under the Apache License, Version 2.0
6
+ * (the "License", destination); you may not use this file except in compliance with
7
+ * the License. You may obtain a copy of the License at
8
+ *
9
+ * https://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ /**
18
+ * Context information for debugging ExTester errors.
19
+ */
20
+ export interface ErrorContext {
21
+ /** Name of the page object component (e.g., "TextEditor", "ActivityBar") */
22
+ component?: string;
23
+ /** The action being performed when the error occurred */
24
+ action?: string;
25
+ /** VS Code version being tested */
26
+ vscodeVersion?: string;
27
+ /** String representation of the locator used */
28
+ locator?: string;
29
+ /** Additional details about the element or operation */
30
+ details?: string;
31
+ /** The original error that caused this error, if any */
32
+ cause?: Error;
33
+ }
34
+ /**
35
+ * Base error class for all ExTester-specific errors.
36
+ * Provides rich context for debugging test failures.
37
+ */
38
+ export declare class ExTesterError extends Error {
39
+ readonly context: ErrorContext;
40
+ readonly timestamp: Date;
41
+ constructor(message: string, context?: ErrorContext);
42
+ /**
43
+ * Get a detailed string representation of the error for logging.
44
+ */
45
+ toDetailedString(): string;
46
+ toString(): string;
47
+ }
48
+ /**
49
+ * Error thrown when an element cannot be found in the DOM.
50
+ */
51
+ export declare class ElementNotFoundError extends ExTesterError {
52
+ constructor(message: string, context?: ErrorContext);
53
+ }
54
+ /**
55
+ * Error thrown when an element exists but is not visible.
56
+ */
57
+ export declare class ElementNotVisibleError extends ExTesterError {
58
+ constructor(message: string, context?: ErrorContext);
59
+ }
60
+ /**
61
+ * Error thrown when an element cannot be interacted with (e.g., blocked, disabled).
62
+ */
63
+ export declare class ElementNotInteractableError extends ExTesterError {
64
+ constructor(message: string, context?: ErrorContext);
65
+ }
66
+ /**
67
+ * Error thrown when an element reference has become stale (DOM was modified).
68
+ */
69
+ export declare class StaleElementError extends ExTesterError {
70
+ constructor(message: string, context?: ErrorContext);
71
+ }
72
+ /**
73
+ * Error thrown when element recovery/reinitialization fails.
74
+ */
75
+ export declare class ElementRecoveryError extends ExTesterError {
76
+ constructor(message: string, context?: ErrorContext);
77
+ }
78
+ /**
79
+ * Error thrown when a timeout occurs waiting for a condition.
80
+ */
81
+ export declare class TimeoutError extends ExTesterError {
82
+ readonly timeoutMs: number;
83
+ constructor(message: string, timeoutMs: number, context?: ErrorContext);
84
+ toDetailedString(): string;
85
+ }
86
+ /**
87
+ * Error thrown when a locator fails to match any elements.
88
+ */
89
+ export declare class LocatorError extends ExTesterError {
90
+ constructor(message: string, context?: ErrorContext);
91
+ }
92
+ /**
93
+ * Error thrown for platform-specific limitations (e.g., macOS native dialogs).
94
+ */
95
+ export declare class PlatformNotSupportedError extends ExTesterError {
96
+ readonly platform: string;
97
+ constructor(message: string, platform?: string, context?: ErrorContext);
98
+ toDetailedString(): string;
99
+ }
100
+ /**
101
+ * Error thrown when an operation is not supported for the current VS Code version.
102
+ */
103
+ export declare class VersionNotSupportedError extends ExTesterError {
104
+ readonly requiredVersion: string;
105
+ readonly currentVersion: string;
106
+ constructor(message: string, requiredVersion: string, currentVersion: string, context?: ErrorContext);
107
+ toDetailedString(): string;
108
+ }
109
+ /**
110
+ * Utility to wrap native Selenium errors with ExTester context.
111
+ */
112
+ export declare function wrapError(originalError: Error, context: ErrorContext): ExTesterError;