@redhat-developer/page-objects 1.0.1 → 1.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.
Files changed (34) hide show
  1. package/README.md +1 -1
  2. package/out/components/AbstractElement.js +2 -2
  3. package/out/components/WebviewMixin.d.ts +1 -1
  4. package/out/components/bottomBar/AbstractViews.d.ts +1 -0
  5. package/out/components/bottomBar/AbstractViews.js +3 -2
  6. package/out/components/bottomBar/BottomBarPanel.js +1 -1
  7. package/out/components/bottomBar/ProblemsView.js +1 -2
  8. package/out/components/bottomBar/WebviewView.js +1 -0
  9. package/out/components/editor/EditorView.js +1 -1
  10. package/out/components/editor/SettingsEditor.d.ts +85 -4
  11. package/out/components/editor/SettingsEditor.js +210 -35
  12. package/out/components/editor/TextEditor.js +5 -5
  13. package/out/components/editor/WebView.js +2 -1
  14. package/out/components/menu/ContextMenu.js +1 -1
  15. package/out/components/menu/Menu.js +2 -1
  16. package/out/components/menu/TitleBar.d.ts +2 -2
  17. package/out/components/menu/TitleBar.js +2 -2
  18. package/out/components/sidebar/ViewContent.js +1 -1
  19. package/out/components/sidebar/ViewSection.js +1 -1
  20. package/out/components/sidebar/debug/DebugView.d.ts +1 -0
  21. package/out/components/sidebar/debug/DebugView.js +2 -1
  22. package/out/components/sidebar/extensions/ExtensionsViewSection.js +1 -1
  23. package/out/components/sidebar/scm/ScmView.d.ts +1 -1
  24. package/out/components/sidebar/scm/ScmView.js +2 -2
  25. package/out/components/sidebar/tree/debug/VariableSectionItem.d.ts +1 -0
  26. package/out/components/sidebar/tree/debug/VariableSectionItem.js +4 -0
  27. package/out/components/workbench/Notification.d.ts +1 -0
  28. package/out/components/workbench/Notification.js +4 -0
  29. package/out/components/workbench/NotificationsCenter.js +1 -1
  30. package/out/conditions/WaitForAttribute.d.ts +1 -1
  31. package/out/conditions/WaitForAttribute.js +1 -1
  32. package/out/locators/loader.js +3 -3
  33. package/out/locators/locators.d.ts +12 -2
  34. package/package.json +5 -3
package/README.md CHANGED
@@ -5,5 +5,5 @@
5
5
  <h2 align="center">Page Objects</h2>
6
6
 
7
7
  <p align="center">
8
- Page Object API implementation for a VS Code editor used by <a href="https://github.com/redhat-developer/vscode-extension-tester">ExTester</a> framework - 📄 <a href="https://github.com/redhat-developer/vscode-extension-tester/wiki/Page-Object-APIs">Documentation</a>.
8
+ Page Object API implementation for a VS Code editor used by <a href="https://github.com/redhat-developer/vscode-extension-tester">ExTester</a> framework.</br>📄 <a href="https://github.com/redhat-developer/vscode-extension-tester/wiki/Page-Object-APIs">Documentation</a>
9
9
  </p>
@@ -32,8 +32,8 @@ class AbstractElement extends selenium_webdriver_1.WebElement {
32
32
  super(AbstractElement.driver, base.getId());
33
33
  }
34
34
  else {
35
- let toFind = item.findElement(base);
36
- let id = toFind.getId();
35
+ const toFind = item.findElement(base);
36
+ const id = toFind.getId();
37
37
  super(AbstractElement.driver, id);
38
38
  }
39
39
  this.enclosingItem = item;
@@ -3,7 +3,7 @@ import { AbstractElement } from "./AbstractElement";
3
3
  /**
4
4
  * Heavily inspired by https://stackoverflow.com/a/65418734
5
5
  */
6
- type Constructor<T = {}> = new (...args: any[]) => T;
6
+ type Constructor<T = object> = new (...args: any[]) => T;
7
7
  /**
8
8
  * The interface that a class is required to have in order to use the Webview mixin.
9
9
  */
@@ -12,6 +12,7 @@ export declare abstract class ChannelView extends ElementWithContexMenu {
12
12
  /**
13
13
  * Get name of the current channel
14
14
  * @returns Promise resolving to the current channel name
15
+ * @deprecated For VS Code 1.88+ this method won't be working any more
15
16
  */
16
17
  getCurrentChannel(): Promise<string>;
17
18
  /**
@@ -27,10 +27,11 @@ class ChannelView extends ElementWithContextMenu_1.ElementWithContexMenu {
27
27
  /**
28
28
  * Get name of the current channel
29
29
  * @returns Promise resolving to the current channel name
30
+ * @deprecated For VS Code 1.88+ this method won't be working any more
30
31
  */
31
32
  async getCurrentChannel() {
32
33
  if (ChannelView.versionInfo.version >= '1.87.0' && process.platform !== 'darwin') {
33
- throw Error(`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.`);
34
+ 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.`);
34
35
  }
35
36
  const combo = await this.enclosingItem.findElement(ChannelView.locators.BottomBarViews.channelCombo);
36
37
  return await combo.getAttribute('title');
@@ -64,7 +65,7 @@ class TextView extends ChannelView {
64
65
  // workaround issue https://github.com/redhat-developer/vscode-extension-tester/issues/835
65
66
  // do not fail if clipboard is empty
66
67
  }
67
- let textarea = await this.findElement(ChannelView.locators.BottomBarViews.textArea);
68
+ const textarea = await this.findElement(ChannelView.locators.BottomBarViews.textArea);
68
69
  await textarea.sendKeys(selenium_webdriver_1.Key.chord(TextView.ctlKey, 'a'));
69
70
  await textarea.sendKeys(selenium_webdriver_1.Key.chord(TextView.ctlKey, 'c'));
70
71
  const text = clipboard.readSync();
@@ -115,7 +115,7 @@ class BottomBarPanel extends AbstractElement_1.AbstractElement {
115
115
  }
116
116
  }
117
117
  async closePanel() {
118
- let closeButton = await this.findElement(BottomBarPanel.locators.BottomBarPanel.closeAction);
118
+ const closeButton = await this.findElement(BottomBarPanel.locators.BottomBarPanel.closeAction);
119
119
  await closeButton.click();
120
120
  }
121
121
  }
@@ -59,8 +59,7 @@ class ProblemsView extends AbstractElement_1.AbstractElement {
59
59
  const markers = [];
60
60
  const elements = await this.findElements(ProblemsView.locators.ProblemsView.markerRow);
61
61
  for (const element of elements) {
62
- let marker;
63
- marker = await new Marker(element, this).wait();
62
+ const marker = await new Marker(element, this).wait();
64
63
  if (type === MarkerType.Any || type === await marker.getType()) {
65
64
  markers.push(marker);
66
65
  }
@@ -13,6 +13,7 @@ class WebviewViewBase extends AbstractElement_1.AbstractElement {
13
13
  constructor() {
14
14
  super(WebviewViewBase.locators.Workbench.constructor);
15
15
  }
16
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
16
17
  async getViewToSwitchTo(handle) {
17
18
  return await this.getDriver().findElement(WebviewViewBase.locators.WebviewView.iframe);
18
19
  }
@@ -124,7 +124,7 @@ class EditorView extends AbstractElement_1.AbstractElement {
124
124
  for (let i = 0; i < groups.length - 1; i++) {
125
125
  for (let j = 0; j < groups.length - i - 1; j++) {
126
126
  if ((await groups[j].getRect()).x > (await groups[j + 1].getRect()).x) {
127
- let temp = groups[j];
127
+ const temp = groups[j];
128
128
  groups[j] = groups[j + 1];
129
129
  groups[j + 1] = temp;
130
130
  }
@@ -1,10 +1,10 @@
1
1
  import { Editor } from "./Editor";
2
2
  import { ContextMenu } from "../menu/ContextMenu";
3
- import { By } from "selenium-webdriver";
3
+ import { WebElement, By } from "selenium-webdriver";
4
4
  import { AbstractElement } from "../AbstractElement";
5
5
  import { EditorView, EditorGroup } from "../..";
6
6
  /**
7
- * Page object representing the internal VSCode settings editor
7
+ * Page object representing the internal VS Code settings editor
8
8
  */
9
9
  export declare class SettingsEditor extends Editor {
10
10
  private divider;
@@ -48,7 +48,7 @@ export declare class SettingsEditor extends Editor {
48
48
  }
49
49
  /**
50
50
  * Abstract item representing a Setting with title, description and
51
- * an input element (combo/textbox/checkbox/link)
51
+ * an input element (combo/textbox/checkbox/link/array)
52
52
  */
53
53
  export declare abstract class Setting extends AbstractElement {
54
54
  constructor(settingsConstructor: By, settings: SettingsEditor);
@@ -91,7 +91,6 @@ export declare class ComboSetting extends Setting {
91
91
  */
92
92
  getValues(): Promise<string[]>;
93
93
  private getOptions;
94
- private openCombo;
95
94
  }
96
95
  /**
97
96
  * Setting with a text box input
@@ -119,3 +118,85 @@ export declare class LinkSetting extends Setting {
119
118
  */
120
119
  openLink(): Promise<void>;
121
120
  }
121
+ /**
122
+ * Setting with an array of string values (rows)
123
+ */
124
+ export declare class ArraySetting extends Setting {
125
+ /**
126
+ * @deprecated Method 'getValue' is not available for ArraySetting!
127
+ */
128
+ getValue(): Promise<string | boolean>;
129
+ /**
130
+ * @deprecated Method 'setValue' is not available for ArraySetting!
131
+ */
132
+ setValue(value: string | boolean): Promise<void>;
133
+ /**
134
+ * Select a row of a setting array of string values
135
+ * @param item label | index
136
+ */
137
+ select(item: string | number): Promise<void>;
138
+ /**
139
+ * Get a row as new ArraySettingItem object
140
+ * @param item label or index
141
+ * @returns ArraySettingItem | undefined
142
+ */
143
+ getItem(item: string | number): Promise<ArraySettingItem | undefined>;
144
+ /**
145
+ * Get a list of all rows as ArraySettingItem objects
146
+ * @returns ArraySettingItem[]
147
+ */
148
+ getItems(): Promise<ArraySettingItem[]>;
149
+ /**
150
+ * Get a list of all rows values
151
+ * @returns string[]
152
+ */
153
+ getValues(): Promise<string[]>;
154
+ /**
155
+ * Click 'Add Item' and get row as ArraySettingItem in edit mode
156
+ * @returns ArraySettingItem
157
+ */
158
+ add(): Promise<ArraySettingItem>;
159
+ /**
160
+ * Select a row, then click 'Edit Item' and get row as ArraySettingItem in edit mode
161
+ * @param item label | index
162
+ * @returns ArraySettingItem | undefined
163
+ */
164
+ edit(item: string | number): Promise<ArraySettingItem | undefined>;
165
+ private getListRootElement;
166
+ private getRows;
167
+ private findRow;
168
+ }
169
+ /**
170
+ * Represents each row of an ArraySetting array of strings
171
+ */
172
+ export declare class ArraySettingItem extends AbstractElement {
173
+ constructor(element: WebElement, setting: ArraySetting);
174
+ /**
175
+ * Select an item
176
+ */
177
+ select(): Promise<void>;
178
+ /**
179
+ * Get item text value
180
+ * @returns string
181
+ */
182
+ getValue(): Promise<string>;
183
+ /**
184
+ * Set item text value
185
+ * @param value string
186
+ */
187
+ setValue(value: string): Promise<void>;
188
+ /**
189
+ * Click 'Remove Item' button
190
+ */
191
+ remove(): Promise<void>;
192
+ /**
193
+ * Click 'OK' button
194
+ * @description Only when the item is in edit mode
195
+ */
196
+ ok(): Promise<void>;
197
+ /**
198
+ * Click 'Cancel' button
199
+ * @description Only when the item is in edit mode
200
+ */
201
+ cancel(): Promise<void>;
202
+ }
@@ -1,12 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.LinkSetting = exports.CheckboxSetting = exports.TextSetting = exports.ComboSetting = exports.Setting = exports.SettingsEditor = void 0;
3
+ exports.ArraySettingItem = exports.ArraySetting = exports.LinkSetting = exports.CheckboxSetting = exports.TextSetting = exports.ComboSetting = exports.Setting = exports.SettingsEditor = void 0;
4
4
  const Editor_1 = require("./Editor");
5
5
  const selenium_webdriver_1 = require("selenium-webdriver");
6
6
  const AbstractElement_1 = require("../AbstractElement");
7
7
  const __1 = require("../..");
8
8
  /**
9
- * Page object representing the internal VSCode settings editor
9
+ * Page object representing the internal VS Code settings editor
10
10
  */
11
11
  class SettingsEditor extends Editor_1.Editor {
12
12
  divider = SettingsEditor.versionInfo.version >= '1.83.0' ? '›' : ' › ';
@@ -63,21 +63,22 @@ class SettingsEditor extends Editor_1.Editor {
63
63
  const items = await this.findElements(SettingsEditor.locators.SettingsEditor.itemRow);
64
64
  for (const item of items) {
65
65
  try {
66
- const _category = (await (await item.findElement(SettingsEditor.locators.SettingsEditor.settingCategory)).getText()).replace(':', '');
67
- const _title = await (await item.findElement(SettingsEditor.locators.SettingsEditor.settingLabel)).getText();
66
+ const itemCategory = (await (await item.findElement(SettingsEditor.locators.SettingsEditor.settingCategory)).getText()).replace(':', '');
67
+ const itemTitle = await (await item.findElement(SettingsEditor.locators.SettingsEditor.settingLabel)).getText();
68
68
  if (category !== '') {
69
- if (category.toLowerCase().replace(this.divider, '').replace(/\s/g, '').trim() !== _category.toLowerCase().replace(this.divider, '').replace(/\s/g, '').trim()) {
69
+ if (category.toLowerCase().replace(this.divider, '').replace(/\s/g, '').trim() !== itemCategory.toLowerCase().replace(this.divider, '').replace(/\s/g, '').trim()) {
70
70
  continue;
71
71
  }
72
72
  }
73
73
  if (title !== '') {
74
- if (title.toLowerCase().replace(/\s/g, '').trim() !== _title.toLowerCase().replace(/\s/g, '').trim()) {
74
+ if (title.toLowerCase().replace(/\s/g, '').trim() !== itemTitle.toLowerCase().replace(/\s/g, '').trim()) {
75
75
  continue;
76
76
  }
77
77
  }
78
- return await (await this.createSetting(item, _title, _category)).wait();
78
+ return await (await this.createSetting(item, itemTitle, itemCategory)).wait();
79
79
  }
80
80
  catch (err) {
81
+ // do nothing
81
82
  }
82
83
  }
83
84
  return setting;
@@ -99,7 +100,7 @@ class SettingsEditor extends Editor_1.Editor {
99
100
  * Context menu is disabled in this editor, throw an error
100
101
  */
101
102
  async openContextMenu() {
102
- throw new Error('Operation not supported');
103
+ throw new Error('Operation not supported!');
103
104
  }
104
105
  async createSetting(element, title, category) {
105
106
  await element.findElement(SettingsEditor.locators.SettingsEditor.settingConstructor(title, category));
@@ -127,7 +128,14 @@ class SettingsEditor extends Editor_1.Editor {
127
128
  return new LinkSetting(SettingsEditor.locators.SettingsEditor.settingConstructor(title, category), this);
128
129
  }
129
130
  catch (err) {
130
- throw new Error('Setting type not supported');
131
+ // try array setting
132
+ try {
133
+ await element.findElement(SettingsEditor.locators.SettingsEditor.arraySetting);
134
+ return new ArraySetting(SettingsEditor.locators.SettingsEditor.settingConstructor(title, category), this);
135
+ }
136
+ catch (err) {
137
+ throw new Error('Setting type not supported!');
138
+ }
131
139
  }
132
140
  }
133
141
  }
@@ -137,7 +145,7 @@ class SettingsEditor extends Editor_1.Editor {
137
145
  exports.SettingsEditor = SettingsEditor;
138
146
  /**
139
147
  * Abstract item representing a Setting with title, description and
140
- * an input element (combo/textbox/checkbox/link)
148
+ * an input element (combo/textbox/checkbox/link/array)
141
149
  */
142
150
  class Setting extends AbstractElement_1.AbstractElement {
143
151
  constructor(settingsConstructor, settings) {
@@ -155,7 +163,7 @@ class Setting extends AbstractElement_1.AbstractElement {
155
163
  * @returns Promise resolving to setting description
156
164
  */
157
165
  async getDescription() {
158
- return await (await this.findElement(SettingsEditor.locators.SettingsEditor.settingDesctiption)).getText();
166
+ return await (await this.findElement(SettingsEditor.locators.SettingsEditor.settingDescription)).getText();
159
167
  }
160
168
  /**
161
169
  * Get title of the setting
@@ -175,9 +183,9 @@ class ComboSetting extends Setting {
175
183
  }
176
184
  async setValue(value) {
177
185
  const rows = await this.getOptions();
178
- for (let row of rows) {
186
+ for (const row of rows) {
179
187
  if ((await row.getAttribute('class')).indexOf('disabled') < 0) {
180
- const text = await (await row.findElement(SettingsEditor.locators.SettingsEditor.comboOption)).getText();
188
+ const text = await row.getAttribute(SettingsEditor.locators.SettingsEditor.comboValue);
181
189
  if (value === text) {
182
190
  return await row.click();
183
191
  }
@@ -192,31 +200,13 @@ class ComboSetting extends Setting {
192
200
  const values = [];
193
201
  const rows = await this.getOptions();
194
202
  for (const row of rows) {
195
- values.push(await (await row.findElement(SettingsEditor.locators.SettingsEditor.comboOption)).getText());
203
+ values.push(await row.getAttribute(SettingsEditor.locators.SettingsEditor.comboValue));
196
204
  }
197
205
  return values;
198
206
  }
199
207
  async getOptions() {
200
- const menu = await this.openCombo();
201
- return await menu.findElements(SettingsEditor.locators.SettingsEditor.itemRow);
202
- }
203
- async openCombo() {
204
208
  const combo = await this.findElement(SettingsEditor.locators.SettingsEditor.comboSetting);
205
- const workbench = await this.getDriver().findElement(SettingsEditor.locators.Workbench.constructor);
206
- const menus = await workbench.findElements(SettingsEditor.locators.ContextMenu.contextView);
207
- let menu;
208
- if (menus.length < 1) {
209
- await combo.click();
210
- menu = await workbench.findElement(SettingsEditor.locators.ContextMenu.contextView);
211
- return menu;
212
- }
213
- else if (await menus[0].isDisplayed()) {
214
- await combo.click();
215
- await this.getDriver().sleep(200);
216
- }
217
- await combo.click();
218
- menu = await workbench.findElement(SettingsEditor.locators.ContextMenu.contextView);
219
- return menu;
209
+ return await combo.findElements(SettingsEditor.locators.SettingsEditor.comboOption);
220
210
  }
221
211
  }
222
212
  exports.ComboSetting = ComboSetting;
@@ -260,10 +250,11 @@ exports.CheckboxSetting = CheckboxSetting;
260
250
  */
261
251
  class LinkSetting extends Setting {
262
252
  async getValue() {
263
- throw new Error('Method getValue is not available for LinkSetting');
253
+ throw new Error('Method getValue is not available for LinkSetting!');
264
254
  }
255
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
265
256
  async setValue(value) {
266
- throw new Error('Method setValue is not available for LinkSetting');
257
+ throw new Error('Method setValue is not available for LinkSetting!');
267
258
  }
268
259
  /**
269
260
  * Open the link that leads to the value in settings.json
@@ -275,4 +266,188 @@ class LinkSetting extends Setting {
275
266
  }
276
267
  }
277
268
  exports.LinkSetting = LinkSetting;
269
+ /**
270
+ * Setting with an array of string values (rows)
271
+ */
272
+ class ArraySetting extends Setting {
273
+ /**
274
+ * @deprecated Method 'getValue' is not available for ArraySetting!
275
+ */
276
+ async getValue() {
277
+ throw new Error('Method \'getValue\' is not available for ArraySetting!');
278
+ }
279
+ /**
280
+ * @deprecated Method 'setValue' is not available for ArraySetting!
281
+ */
282
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
283
+ async setValue(value) {
284
+ throw new Error('Method \'setValue\' is not available for ArraySetting!');
285
+ }
286
+ /**
287
+ * Select a row of a setting array of string values
288
+ * @param item label | index
289
+ */
290
+ async select(item) {
291
+ const toSelect = await this.getItem(item);
292
+ await toSelect?.select();
293
+ }
294
+ /**
295
+ * Get a row as new ArraySettingItem object
296
+ * @param item label or index
297
+ * @returns ArraySettingItem | undefined
298
+ */
299
+ async getItem(item) {
300
+ const row = await this.findRow(item);
301
+ if (row) {
302
+ return new ArraySettingItem(row, this);
303
+ }
304
+ return undefined;
305
+ }
306
+ /**
307
+ * Get a list of all rows as ArraySettingItem objects
308
+ * @returns ArraySettingItem[]
309
+ */
310
+ async getItems() {
311
+ const listRows = await this.getRows();
312
+ const items = [];
313
+ for (const row of listRows) {
314
+ items.push(new ArraySettingItem(row, this));
315
+ }
316
+ return items;
317
+ }
318
+ /**
319
+ * Get a list of all rows values
320
+ * @returns string[]
321
+ */
322
+ async getValues() {
323
+ const items = await this.getItems();
324
+ const values = [];
325
+ for (const item of items) {
326
+ values.push(await item.getValue());
327
+ }
328
+ return values;
329
+ }
330
+ /**
331
+ * Click 'Add Item' and get row as ArraySettingItem in edit mode
332
+ * @returns ArraySettingItem
333
+ */
334
+ async add() {
335
+ // click 'Add Item' button
336
+ const button = await this.findElement(SettingsEditor.locators.SettingsEditor.arrayNewRow).findElement(selenium_webdriver_1.By.className('monaco-button'));
337
+ await button.click();
338
+ await new Promise(sleep => setTimeout(sleep, 1_000)); // need to force some time to allow DOM rerender elements
339
+ // get item row switched to 'edit' mode
340
+ const list = await this.getListRootElement();
341
+ const editRow = await list.findElement(SettingsEditor.locators.SettingsEditor.arrayEditRow);
342
+ return new ArraySettingItem(editRow, this);
343
+ }
344
+ /**
345
+ * Select a row, then click 'Edit Item' and get row as ArraySettingItem in edit mode
346
+ * @param item label | index
347
+ * @returns ArraySettingItem | undefined
348
+ */
349
+ async edit(item) {
350
+ const row = await this.findRow(item);
351
+ if (row) {
352
+ // select item row
353
+ const toEdit = new ArraySettingItem(row, this);
354
+ await toEdit.select();
355
+ // click 'Edit Item' button
356
+ const edit = await toEdit.findElement(SettingsEditor.locators.SettingsEditor.arrayBtnConstructor('Edit Item'));
357
+ await edit.click();
358
+ await new Promise(sleep => setTimeout(sleep, 1_000)); // need to force some time to allow DOM rerender elements
359
+ // get item row switched to 'edit' mode
360
+ const list = await this.getListRootElement();
361
+ const editRow = await list.findElement(SettingsEditor.locators.SettingsEditor.arrayEditRow);
362
+ return new ArraySettingItem(editRow, this);
363
+ }
364
+ return undefined;
365
+ }
366
+ async getListRootElement() {
367
+ return await this.findElement(SettingsEditor.locators.SettingsEditor.arrayRoot);
368
+ }
369
+ async getRows() {
370
+ const list = await this.getListRootElement();
371
+ return await list.findElements(SettingsEditor.locators.SettingsEditor.arrayRow);
372
+ }
373
+ async findRow(item) {
374
+ const listRows = await this.getRows();
375
+ if (Number.isInteger(item)) {
376
+ const index = +item;
377
+ if (index < 0 || index > listRows.length - 1) {
378
+ throw Error(`Index '${index}' is of bounds! Found items have length = ${listRows.length}.`);
379
+ }
380
+ return listRows[index];
381
+ }
382
+ else {
383
+ for (const row of listRows) {
384
+ const li = await row.findElement(SettingsEditor.locators.SettingsEditor.arrayRowValue);
385
+ if (await li.getText() === item) {
386
+ return row;
387
+ }
388
+ }
389
+ }
390
+ return undefined;
391
+ }
392
+ }
393
+ exports.ArraySetting = ArraySetting;
394
+ /**
395
+ * Represents each row of an ArraySetting array of strings
396
+ */
397
+ class ArraySettingItem extends AbstractElement_1.AbstractElement {
398
+ constructor(element, setting) {
399
+ super(element, setting);
400
+ }
401
+ /**
402
+ * Select an item
403
+ */
404
+ async select() {
405
+ await this.click();
406
+ await new Promise(sleep => setTimeout(sleep, 500));
407
+ }
408
+ /**
409
+ * Get item text value
410
+ * @returns string
411
+ */
412
+ async getValue() {
413
+ return await this.getText();
414
+ }
415
+ /**
416
+ * Set item text value
417
+ * @param value string
418
+ */
419
+ async setValue(value) {
420
+ const input = await this.findElement(SettingsEditor.locators.SettingsEditor.textSetting);
421
+ await input.clear();
422
+ await input.sendKeys(value);
423
+ }
424
+ /**
425
+ * Click 'Remove Item' button
426
+ */
427
+ async remove() {
428
+ await this.select();
429
+ const remove = await this.findElement(SettingsEditor.locators.SettingsEditor.arrayBtnConstructor('Remove Item'));
430
+ await remove.click();
431
+ await new Promise(sleep => setTimeout(sleep, 500));
432
+ }
433
+ /**
434
+ * Click 'OK' button
435
+ * @description Only when the item is in edit mode
436
+ */
437
+ async ok() {
438
+ const ok = await this.findElement(SettingsEditor.locators.SettingsEditor.arraySettingItem.btnConstructor('OK'));
439
+ await ok.click();
440
+ await new Promise(sleep => setTimeout(sleep, 500));
441
+ }
442
+ /**
443
+ * Click 'Cancel' button
444
+ * @description Only when the item is in edit mode
445
+ */
446
+ async cancel() {
447
+ const cancel = await this.findElement(SettingsEditor.locators.SettingsEditor.arraySettingItem.btnConstructor('Cancel'));
448
+ await cancel.click();
449
+ await new Promise(sleep => setTimeout(sleep, 500));
450
+ }
451
+ }
452
+ exports.ArraySettingItem = ArraySettingItem;
278
453
  //# sourceMappingURL=SettingsEditor.js.map
@@ -220,7 +220,7 @@ class TextEditor extends Editor_1.Editor {
220
220
  let actions = this.getDriver().actions();
221
221
  await actions.clear();
222
222
  actions.keyDown(selenium_webdriver_1.Key.SHIFT);
223
- for (const _i of text) {
223
+ for (let i = 0; i < text.length; i++) {
224
224
  actions = actions.sendKeys(selenium_webdriver_1.Key.RIGHT);
225
225
  }
226
226
  actions = actions.keyUp(selenium_webdriver_1.Key.SHIFT);
@@ -273,7 +273,7 @@ class TextEditor extends Editor_1.Editor {
273
273
  return new Selection(selection[0], this);
274
274
  }
275
275
  async openFindWidget() {
276
- let actions = this.getDriver().actions();
276
+ const actions = this.getDriver().actions();
277
277
  await actions.clear();
278
278
  await actions.keyDown(TextEditor.ctlKey).sendKeys('f').keyUp(TextEditor.ctlKey).perform();
279
279
  const widget = await this.getDriver().wait(selenium_webdriver_1.until.elementLocated(TextEditor.locators.TextEditor.findWidget), 2000);
@@ -331,8 +331,8 @@ class TextEditor extends Editor_1.Editor {
331
331
  const columnKey = columnGap >= 0 ? selenium_webdriver_1.Key.LEFT : selenium_webdriver_1.Key.RIGHT;
332
332
  for (let i = 0; i < Math.abs(columnGap); i++) {
333
333
  await inputarea.sendKeys(columnKey);
334
- let actualCoordinates = (await this.getCoordinates())[0];
335
- if (actualCoordinates != coordinates[0]) {
334
+ const actualCoordinates = (await this.getCoordinates())[0];
335
+ if (actualCoordinates !== coordinates[0]) {
336
336
  throw new Error(`Column number ${column} is not accessible on line ${line}`);
337
337
  }
338
338
  }
@@ -412,7 +412,7 @@ class TextEditor extends Editor_1.Editor {
412
412
  const breakpointContainer = TextEditor.versionInfo.version >= '1.80.0' ? await this.findElement(selenium_webdriver_1.By.className('glyph-margin-widgets')) : lineOverlay;
413
413
  const breakPoint = await breakpointContainer.findElements(TextEditor.locators.TextEditor.breakpoint.generalSelector);
414
414
  if (breakPoint.length > 0) {
415
- if (this.breakPoints.indexOf(line) != -1) {
415
+ if (this.breakPoints.indexOf(line) !== -1) {
416
416
  await breakPoint[this.breakPoints.indexOf(line)].click();
417
417
  await new Promise(res => setTimeout(res, 200));
418
418
  this.breakPoints.splice(this.breakPoints.indexOf(line), 1);
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.WebView = void 0;
7
+ /* eslint-disable no-redeclare */
7
8
  const selenium_webdriver_1 = require("selenium-webdriver");
8
9
  const WebviewMixin_1 = __importDefault(require("../WebviewMixin"));
9
10
  const Editor_1 = require("./Editor");
@@ -24,7 +25,7 @@ class WebViewBase extends Editor_1.Editor {
24
25
  const reference = await this.findElement(WebViewBase.locators.EditorView.webView);
25
26
  const containers = await this.getDriver().wait(selenium_webdriver_1.until.elementsLocated(WebViewBase.locators.WebView.container(await reference.getAttribute(WebViewBase.locators.WebView.attribute))), 5000);
26
27
  return await containers[0].getDriver().wait(async () => {
27
- for (let container of containers) {
28
+ for (const container of containers) {
28
29
  const tries = await container.findElements(WebViewBase.locators.WebView.iframe);
29
30
  if (tries.length > 0) {
30
31
  return tries[0];
@@ -48,7 +48,7 @@ class ContextMenu extends __1.Menu {
48
48
  * @returns Promise resolving when the menu is closed
49
49
  */
50
50
  async close() {
51
- let actions = this.getDriver().actions();
51
+ const actions = this.getDriver().actions();
52
52
  await actions.clear();
53
53
  await this.getDriver().actions().sendKeys(selenium_webdriver_1.Key.ESCAPE).perform();
54
54
  try {
@@ -33,8 +33,9 @@ class Menu extends AbstractElement_1.AbstractElement {
33
33
  let parent = this;
34
34
  for (const label of path) {
35
35
  const item = await parent.getItem(label);
36
- if (!item)
36
+ if (!item) {
37
37
  return parent;
38
+ }
38
39
  await Menu.driver.wait(async function () {
39
40
  return await item.isDisplayed() && await item.isEnabled();
40
41
  });
@@ -2,7 +2,7 @@ import { WindowControls, ContextMenu } from "../..";
2
2
  import { Menu } from "./Menu";
3
3
  import { MenuItem } from "./MenuItem";
4
4
  /**
5
- * Page object representing the custom VSCode title bar
5
+ * Page object representing the custom VS Code title bar
6
6
  */
7
7
  export declare class TitleBar extends Menu {
8
8
  constructor();
@@ -28,7 +28,7 @@ export declare class TitleBar extends Menu {
28
28
  getWindowControls(): WindowControls;
29
29
  }
30
30
  /**
31
- * Page object representing an item of the custom VSCode title bar
31
+ * Page object representing an item of the custom VS Code title bar
32
32
  */
33
33
  export declare class TitleBarItem extends MenuItem {
34
34
  constructor(label: string, parent: Menu);
@@ -6,7 +6,7 @@ const __1 = require("../..");
6
6
  const Menu_1 = require("./Menu");
7
7
  const MenuItem_1 = require("./MenuItem");
8
8
  /**
9
- * Page object representing the custom VSCode title bar
9
+ * Page object representing the custom VS Code title bar
10
10
  */
11
11
  class TitleBar extends Menu_1.Menu {
12
12
  constructor() {
@@ -56,7 +56,7 @@ class TitleBar extends Menu_1.Menu {
56
56
  }
57
57
  exports.TitleBar = TitleBar;
58
58
  /**
59
- * Page object representing an item of the custom VSCode title bar
59
+ * Page object representing an item of the custom VS Code title bar
60
60
  */
61
61
  class TitleBarItem extends MenuItem_1.MenuItem {
62
62
  constructor(label, parent) {
@@ -58,7 +58,7 @@ class ViewContent extends AbstractElement_1.AbstractElement {
58
58
  if (type !== undefined) {
59
59
  return new type(panel, this);
60
60
  }
61
- let section = new __1.DefaultTreeSection(panel, this);
61
+ const section = new __1.DefaultTreeSection(panel, this);
62
62
  const types = ViewContent.locators.DefaultTreeSection.type;
63
63
  const locators = ViewContent.locators;
64
64
  if (await types.default(section, locators)) {
@@ -109,7 +109,7 @@ class ViewSection extends AbstractElement_1.AbstractElement {
109
109
  * @returns ContextMenu page object if the action succeeds, undefined otherwise
110
110
  */
111
111
  async moreActions() {
112
- let more = await this.getAction('More Actions...');
112
+ const more = await this.getAction('More Actions...');
113
113
  if (!more) {
114
114
  return undefined;
115
115
  }
@@ -8,6 +8,7 @@ export declare class DebugView extends SideBarView {
8
8
  /**
9
9
  * Get the title of the selected launch configuration
10
10
  * @returns Promise resolving to the title
11
+ * @deprecated For VS Code 1.88+ this method won't be working any more
11
12
  */
12
13
  getLaunchConfiguration(): Promise<string>;
13
14
  /**
@@ -11,10 +11,11 @@ class DebugView extends SideBarView_1.SideBarView {
11
11
  /**
12
12
  * Get the title of the selected launch configuration
13
13
  * @returns Promise resolving to the title
14
+ * @deprecated For VS Code 1.88+ this method won't be working any more
14
15
  */
15
16
  async getLaunchConfiguration() {
16
17
  if (DebugView.versionInfo.version >= '1.87.0' && process.platform !== 'darwin') {
17
- throw Error(`The 'DebugView.getLaunchConfiguration' method is broken! Read more information in 'Known Issues > Limitations in testing with VS Code 1.87+' - https://github.com/microsoft/vscode/issues/206897.`);
18
+ throw Error(`DEPRECATED METHOD! The 'DebugView.getLaunchConfiguration' method is broken! Read more information in 'Known Issues > Limitations in testing with VS Code 1.87+' - https://github.com/microsoft/vscode/issues/206897.`);
18
19
  }
19
20
  const action = await this.getTitlePart().findElement(DebugView.locators.DebugView.launchCombo);
20
21
  const combo = await action.findElement(DebugView.locators.DebugView.launchSelect);
@@ -51,7 +51,7 @@ class ExtensionsViewSection extends ViewSection_1.ViewSection {
51
51
  }
52
52
  await this.getDriver().wait(selenium_webdriver_1.until.elementIsNotVisible(progress));
53
53
  const parent = this.enclosingItem;
54
- let sectionTitle = this.getSectionForCategory(title);
54
+ const sectionTitle = this.getSectionForCategory(title);
55
55
  const section = await parent.getSection(sectionTitle);
56
56
  const titleParts = title.split(' ');
57
57
  if (titleParts[0].startsWith('@')) {
@@ -20,7 +20,7 @@ export declare class ScmView extends SideBarView {
20
20
  getProviders(): Promise<ScmProvider[]>;
21
21
  /**
22
22
  * Initialize repository in the current folder if no SCM provider is found
23
- * @returns true if the action was completed succesfully, false if a provider already exists
23
+ * @returns true if the action was completed successfully, false if a provider already exists
24
24
  */
25
25
  initializeRepository(): Promise<boolean>;
26
26
  }
@@ -35,7 +35,7 @@ class ScmView extends SideBarView_1.SideBarView {
35
35
  }
36
36
  /**
37
37
  * Initialize repository in the current folder if no SCM provider is found
38
- * @returns true if the action was completed succesfully, false if a provider already exists
38
+ * @returns true if the action was completed successfully, false if a provider already exists
39
39
  */
40
40
  async initializeRepository() {
41
41
  const buttons = await this.findElements(ScmView.locators.ScmView.initButton);
@@ -242,7 +242,7 @@ class MoreAction extends ElementWithContextMenu_1.ElementWithContexMenu {
242
242
  async openContextMenu() {
243
243
  await this.click();
244
244
  const shadowRootHost = await this.enclosingItem.findElements(selenium_webdriver_1.By.className('shadow-root-host'));
245
- let actions = this.getDriver().actions();
245
+ const actions = this.getDriver().actions();
246
246
  await actions.clear();
247
247
  await actions.sendKeys(selenium_webdriver_1.Key.ESCAPE).perform();
248
248
  const webdriverCapabilities = await this.getDriver().getCapabilities();
@@ -16,6 +16,7 @@ export declare class VariableSectionItem extends CustomTreeItem {
16
16
  /**
17
17
  * Get variable name tooltip.
18
18
  * @returns a promise resolving to variable name tooltip string
19
+ * @deprecated For VS Code 1.88+ this method won't be working any more
19
20
  */
20
21
  getVariableNameTooltip(): Promise<string>;
21
22
  /**
@@ -26,8 +26,12 @@ class VariableSectionItem extends CustomTreeItem_1.CustomTreeItem {
26
26
  /**
27
27
  * Get variable name tooltip.
28
28
  * @returns a promise resolving to variable name tooltip string
29
+ * @deprecated For VS Code 1.88+ this method won't be working any more
29
30
  */
30
31
  async getVariableNameTooltip() {
32
+ if (VariableSectionItem.versionInfo.version >= '1.88.0') {
33
+ throw Error(`DEPRECATED METHOD! For VS Code 1.88+ this method won't be working any more.`);
34
+ }
31
35
  const name = await this.findElement(VariableSectionItem.locators.VariableSectionItem.name.constructor);
32
36
  return VariableSectionItem.locators.VariableSectionItem.name.tooltip(name);
33
37
  }
@@ -27,6 +27,7 @@ export declare abstract class Notification extends ElementWithContexMenu {
27
27
  /**
28
28
  * Get the source of the notification as text
29
29
  * @returns Promise resolving to notification source
30
+ * @deprecated For VS Code 1.88+ this method won't be working any more
30
31
  */
31
32
  getSource(): Promise<string>;
32
33
  /**
@@ -44,8 +44,12 @@ class Notification extends ElementWithContextMenu_1.ElementWithContexMenu {
44
44
  /**
45
45
  * Get the source of the notification as text
46
46
  * @returns Promise resolving to notification source
47
+ * @deprecated For VS Code 1.88+ this method won't be working any more
47
48
  */
48
49
  async getSource() {
50
+ if (Notification.versionInfo.version >= '1.88.0') {
51
+ throw Error(`DEPRECATED METHOD! For VS Code 1.88+ this method won't be working any more.`);
52
+ }
49
53
  await this.expand();
50
54
  return await (await this.findElement(Notification.locators.Notification.source)).getAttribute('title');
51
55
  }
@@ -22,7 +22,7 @@ class NotificationsCenter extends AbstractElement_1.AbstractElement {
22
22
  }
23
23
  catch (error) {
24
24
  await this.click();
25
- this.getDriver().actions().sendKeys(selenium_webdriver_1.Key.ESCAPE).perform();
25
+ await this.getDriver().actions().sendKeys(selenium_webdriver_1.Key.ESCAPE).perform();
26
26
  }
27
27
  }
28
28
  }
@@ -1,7 +1,7 @@
1
1
  import { WebElement } from "selenium-webdriver";
2
2
  /**
3
3
  * Condition to wait until an element's attribute has a specified value
4
- * @param element webelement to check
4
+ * @param element WebElement to check
5
5
  * @param attribute attribute to check
6
6
  * @param value value to wait for the attribute to have
7
7
  */
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.waitForAttributeValue = void 0;
4
4
  /**
5
5
  * Condition to wait until an element's attribute has a specified value
6
- * @param element webelement to check
6
+ * @param element WebElement to check
7
7
  * @param attribute attribute to check
8
8
  * @param value value to wait for the attribute to have
9
9
  */
@@ -74,7 +74,7 @@ class LocatorLoader {
74
74
  (0, compare_versions_1.compareVersions)(ver, this.version) >= 0)
75
75
  .sort(compare_versions_1.compareVersions).reverse();
76
76
  }
77
- for (let version of versions) {
77
+ for (const version of versions) {
78
78
  const diff = require(path.join(this.baseFolder, version)).diff;
79
79
  const newLocators = mergeLocators(this.locators, diff);
80
80
  this.locators = newLocators;
@@ -94,8 +94,8 @@ function merge(target, obj) {
94
94
  if (key === '__proto__' || !Object.prototype.hasOwnProperty.call(obj, key)) {
95
95
  continue;
96
96
  }
97
- let oldVal = obj[key];
98
- let newVal = target[key];
97
+ const oldVal = obj[key];
98
+ const newVal = target[key];
99
99
  if (typeof (newVal) === 'object' && typeof (oldVal) === 'object') {
100
100
  target[key] = merge(newVal, oldVal);
101
101
  }
@@ -156,7 +156,7 @@ export interface Locators {
156
156
  actions: By;
157
157
  action: (label: string) => By;
158
158
  settingConstructor: (title: string, category: string) => By;
159
- settingDesctiption: By;
159
+ settingDescription: By;
160
160
  settingLabel: By;
161
161
  settingCategory: By;
162
162
  comboSetting: By;
@@ -167,6 +167,16 @@ export interface Locators {
167
167
  checkboxChecked: string;
168
168
  linkButton: By;
169
169
  itemCount: By;
170
+ arraySetting: By;
171
+ arrayRoot: By;
172
+ arrayRow: By;
173
+ arrayRowValue: By;
174
+ arrayNewRow: By;
175
+ arrayEditRow: By;
176
+ arrayBtnConstructor: (label: string) => By;
177
+ arraySettingItem: {
178
+ btnConstructor: (label: string) => By;
179
+ };
170
180
  };
171
181
  DiffEditor: {
172
182
  originalEditor: By;
@@ -452,7 +462,7 @@ export interface Locators {
452
462
  */
453
463
  export interface LocatorDiff {
454
464
  locators: PartialDeep<Locators>;
455
- extras?: Object;
465
+ extras?: object;
456
466
  }
457
467
  export declare function hasAttribute(attr: string, value?: string, locator?: By): ((el: WebElement) => Promise<boolean>);
458
468
  export declare function hasClass(classOrPredicate: string | ((klass: string) => boolean), locator?: By): ((el: WebElement) => Promise<boolean>);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redhat-developer/page-objects",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
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",
@@ -10,7 +10,9 @@
10
10
  ],
11
11
  "scripts": {
12
12
  "prepack": "npm run build",
13
- "build": "npm run clean && tsc",
13
+ "build": "npm run clean && npm run compile",
14
+ "compile": "tsc -p ./ && npm run lint",
15
+ "lint": "eslint src --ext .ts",
14
16
  "clean": "rimraf out"
15
17
  },
16
18
  "author": "Red Hat",
@@ -44,5 +46,5 @@
44
46
  "selenium-webdriver": ">=4.6.1",
45
47
  "typescript": ">=4.6.2"
46
48
  },
47
- "gitHead": "8289ad5bca4ff75fe32e61fa49d44ba77bce8954"
49
+ "gitHead": "466d3c63ba056100ba48685e2a6581ae37a38c2a"
48
50
  }