@theia/playwright 1.24.0-next.40 → 1.24.0-next.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theia/playwright",
3
- "version": "1.24.0-next.40+798f9d08504",
3
+ "version": "1.24.0-next.43+2ba15749ca9",
4
4
  "description": "System tests for Theia",
5
5
  "license": "EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0",
6
6
  "repository": {
@@ -39,5 +39,5 @@
39
39
  "publishConfig": {
40
40
  "access": "public"
41
41
  },
42
- "gitHead": "798f9d08504570fce130b9073d398c6782003c0d"
42
+ "gitHead": "2ba15749ca9c334f486eacd3e441663a3fa02927"
43
43
  }
@@ -21,7 +21,7 @@ import { TheiaMenuItem } from './theia-menu-item';
21
21
  import { TheiaRenameDialog } from './theia-rename-dialog';
22
22
  import { TheiaTreeNode } from './theia-tree-node';
23
23
  import { TheiaView } from './theia-view';
24
- import { elementContainsClass, normalizeId } from './util';
24
+ import { elementContainsClass, normalizeId, OSUtil, urlEncodePath } from './util';
25
25
 
26
26
  const TheiaExplorerViewData = {
27
27
  tabSelector: '#shell-tab-explorer-view-container',
@@ -75,16 +75,17 @@ export class TheiaExplorerView extends TheiaView {
75
75
  }
76
76
 
77
77
  async refresh(): Promise<void> {
78
- await this.clickButton('__explorer-view-container_title:navigator.refresh');
78
+ await this.clickButton('navigator.refresh');
79
79
  }
80
80
 
81
81
  async collapseAll(): Promise<void> {
82
- await this.clickButton('__explorer-view-container_title:navigator.collapse.all');
82
+ await this.clickButton('navigator.collapse.all');
83
83
  }
84
84
 
85
85
  protected async clickButton(id: string): Promise<void> {
86
86
  await this.activate();
87
87
  const viewElement = await this.viewElement();
88
+ await viewElement?.hover();
88
89
  const button = await viewElement?.waitForSelector(`#${normalizeId(id)}`);
89
90
  await button?.click();
90
91
  }
@@ -161,7 +162,11 @@ export class TheiaExplorerView extends TheiaView {
161
162
 
162
163
  protected treeNodeId(filePath: string): string {
163
164
  const workspacePath = this.app.workspace.path;
164
- return `${workspacePath}:${workspacePath}/${filePath}`;
165
+ const nodeId = `${workspacePath}:${workspacePath}${OSUtil.fileSeparator}${filePath}`;
166
+ if (OSUtil.isWindows) {
167
+ return urlEncodePath(nodeId);
168
+ }
169
+ return nodeId;
165
170
  }
166
171
 
167
172
  async clickContextMenuItem(file: string, path: string[]): Promise<void> {
@@ -199,8 +204,7 @@ export class TheiaExplorerView extends TheiaView {
199
204
 
200
205
  async getNumberOfVisibleNodes(): Promise<number> {
201
206
  await this.activate();
202
- await this.app.quickCommandPalette.type('Refresh in Explorer');
203
- await this.app.quickCommandPalette.trigger('File: Refresh in Explorer');
207
+ await this.refresh();
204
208
  const fileStatElements = await this.visibleFileStatNodes(DOT_FILES_FILTER);
205
209
  return fileStatElements.length;
206
210
  }
@@ -224,6 +228,7 @@ export class TheiaExplorerView extends TheiaView {
224
228
  await renameDialog.enterNewName(newName);
225
229
  confirm ? await renameDialog.confirm() : await renameDialog.close();
226
230
  await renameDialog.waitForClosed();
231
+ await this.refresh();
227
232
  }
228
233
 
229
234
  }
@@ -16,14 +16,14 @@
16
16
 
17
17
  import { ElementHandle } from '@playwright/test';
18
18
  import { TheiaPageObject } from './theia-page-object';
19
- import { USER_KEY_TYPING_DELAY } from './util';
19
+ import { OSUtil, USER_KEY_TYPING_DELAY } from './util';
20
20
 
21
21
  export class TheiaQuickCommandPalette extends TheiaPageObject {
22
22
 
23
23
  selector = '.quick-input-widget';
24
24
 
25
25
  async open(): Promise<void> {
26
- await this.page.keyboard.press('Control+Shift+p');
26
+ await this.page.keyboard.press(OSUtil.isMacOS ? 'Meta+Shift+p' : 'Control+Shift+p');
27
27
  await this.page.waitForSelector(this.selector);
28
28
  }
29
29
 
@@ -15,13 +15,13 @@
15
15
  // *****************************************************************************
16
16
 
17
17
  import { TheiaDialog } from './theia-dialog';
18
- import { USER_KEY_TYPING_DELAY } from './util';
18
+ import { OSUtil, USER_KEY_TYPING_DELAY } from './util';
19
19
 
20
20
  export class TheiaRenameDialog extends TheiaDialog {
21
21
 
22
22
  async enterNewName(newName: string): Promise<void> {
23
23
  const inputField = await this.page.waitForSelector(`${this.blockSelector} .theia-input`);
24
- await inputField.press('Control+a');
24
+ await inputField.press(OSUtil.isMacOS ? 'Meta+a' : 'Control+a');
25
25
  await inputField.type(newName, { delay: USER_KEY_TYPING_DELAY });
26
26
  await this.page.waitForTimeout(USER_KEY_TYPING_DELAY);
27
27
  }
@@ -15,17 +15,20 @@
15
15
  // *****************************************************************************
16
16
 
17
17
  import { ElementHandle } from '@playwright/test';
18
+ import { join } from 'path';
18
19
 
19
20
  import { TheiaApp } from './theia-app';
20
21
  import { TheiaEditor } from './theia-editor';
21
- import { normalizeId } from './util';
22
+ import { normalizeId, OSUtil, urlEncodePath } from './util';
22
23
 
23
24
  export class TheiaTextEditor extends TheiaEditor {
24
25
 
25
26
  constructor(filePath: string, app: TheiaApp) {
27
+ // shell-tab-code-editor-opener:file:///c%3A/Users/user/AppData/Local/Temp/cloud-ws-JBUhb6/sample.txt:1
28
+ // code-editor-opener:file:///c%3A/Users/user/AppData/Local/Temp/cloud-ws-JBUhb6/sample.txt:1
26
29
  super({
27
- tabSelector: normalizeId(`#shell-tab-code-editor-opener:file://${app.workspace.escapedPath}/${filePath}:1`),
28
- viewSelector: normalizeId(`#code-editor-opener:file://${app.workspace.escapedPath}/${filePath}:1`) + '.theia-editor'
30
+ tabSelector: normalizeId(`#shell-tab-code-editor-opener:file://${urlEncodePath(join(app.workspace.escapedPath, OSUtil.fileSeparator, filePath))}:1`),
31
+ viewSelector: normalizeId(`#code-editor-opener:file://${urlEncodePath(join(app.workspace.escapedPath, OSUtil.fileSeparator, filePath))}:1`) + '.theia-editor'
29
32
  }, app);
30
33
  }
31
34
 
package/src/theia-view.ts CHANGED
@@ -50,6 +50,7 @@ export class TheiaView extends TheiaPageObject {
50
50
  if (!this.data.viewName) {
51
51
  throw new Error('View name must be specified to open via command palette');
52
52
  }
53
+ await this.app.quickCommandPalette.type('View: Open View');
53
54
  await this.app.quickCommandPalette.trigger('View: Open View...', this.data.viewName);
54
55
  await this.waitForVisible();
55
56
  return this;
@@ -15,9 +15,8 @@
15
15
  // *****************************************************************************
16
16
 
17
17
  import * as fs from 'fs-extra';
18
- import { tmpdir } from 'os';
19
- import { sep } from 'path';
20
- import * as path from 'path';
18
+ import { resolve } from 'path';
19
+ import { OSUtil, urlEncodePath } from './util';
21
20
 
22
21
  export class TheiaWorkspace {
23
22
 
@@ -30,14 +29,14 @@ export class TheiaWorkspace {
30
29
  * @param {string[]} pathOfFilesToInitialize Path to files or folders that shall be copied to the workspace
31
30
  */
32
31
  constructor(protected pathOfFilesToInitialize?: string[]) {
33
- this.workspacePath = fs.mkdtempSync(`${tmpdir}${sep}cloud-ws-`);
32
+ this.workspacePath = fs.mkdtempSync(`${OSUtil.tmpDir}${OSUtil.fileSeparator}cloud-ws-`);
34
33
  }
35
34
 
36
35
  /** Performs the file system operations preparing the workspace location synchronously. */
37
36
  initialize(): void {
38
37
  if (this.pathOfFilesToInitialize) {
39
38
  for (const initPath of this.pathOfFilesToInitialize) {
40
- const absoluteInitPath = path.resolve(process.cwd(), initPath);
39
+ const absoluteInitPath = resolve(process.cwd(), initPath);
41
40
  if (!fs.pathExistsSync(absoluteInitPath)) {
42
41
  throw Error('Workspace does not exist at ' + absoluteInitPath);
43
42
  }
@@ -47,15 +46,23 @@ export class TheiaWorkspace {
47
46
  }
48
47
 
49
48
  get path(): string {
50
- return this.workspacePath;
49
+ let workspacePath = this.workspacePath;
50
+ if (!OSUtil.osStartsWithFileSeparator(this.workspacePath)) {
51
+ workspacePath = `${OSUtil.fileSeparator}${workspacePath}`;
52
+ }
53
+ if (OSUtil.isWindows) {
54
+ // Drive letters in windows paths have to be lower case
55
+ workspacePath = workspacePath.replace(/.:/, matchedChar => matchedChar.toLowerCase());
56
+ }
57
+ return workspacePath;
51
58
  }
52
59
 
53
60
  get urlEncodedPath(): string {
54
- return this.path.replace(/[\\]/g, '/');
61
+ return urlEncodePath(this.path);
55
62
  }
56
63
 
57
64
  get escapedPath(): string {
58
- return this.path.replace(/:/g, '%3A').replace(/[\\]/g, '%5C');
65
+ return this.path.replace(/:/g, '%3A');
59
66
  }
60
67
 
61
68
  clear(): void {
package/src/util.ts CHANGED
@@ -15,6 +15,8 @@
15
15
  // *****************************************************************************
16
16
 
17
17
  import { ElementHandle } from '@playwright/test';
18
+ import { tmpdir, platform } from 'os';
19
+ import { sep } from 'path';
18
20
 
19
21
  export const USER_KEY_TYPING_DELAY = 80;
20
22
 
@@ -23,6 +25,10 @@ export function normalizeId(nodeId: string): string {
23
25
  return nodeId.replace(/[.:,%/\\]/g, matchedChar => '\\' + matchedChar);
24
26
  }
25
27
 
28
+ export function urlEncodePath(path: string): string {
29
+ return path.replace(/\\/g, '/');
30
+ }
31
+
26
32
  export async function toTextContentArray(items: ElementHandle<SVGElement | HTMLElement>[]): Promise<string[]> {
27
33
  const contents = items.map(item => item.textContent());
28
34
  const resolvedContents = await Promise.all(contents);
@@ -70,3 +76,16 @@ export async function elementId(element: ElementHandle<SVGElement | HTMLElement>
70
76
  if (id === null) { throw new Error('Could not get ID of ' + element); }
71
77
  return id;
72
78
  }
79
+
80
+ export namespace OSUtil {
81
+ export const isWindows = platform() === 'win32';
82
+ export const isMacOS = platform() === 'darwin';
83
+ // The platform-specific file separator '\' or '/'.
84
+ export const fileSeparator = sep;
85
+ // The platform-specific location of the temporary directory.
86
+ export const tmpDir = tmpdir();
87
+
88
+ export function osStartsWithFileSeparator(path: string): boolean {
89
+ return path.startsWith(fileSeparator);
90
+ }
91
+ }