@theia/playwright 1.23.0-next.26

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.
@@ -0,0 +1,229 @@
1
+ /********************************************************************************
2
+ * Copyright (C) 2021 logi.cals GmbH, EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the Eclipse Public License v. 2.0 which is available at
6
+ * http://www.eclipse.org/legal/epl-2.0.
7
+ *
8
+ * This Source Code may also be made available under the following Secondary
9
+ * Licenses when the conditions for such availability set forth in the Eclipse
10
+ * Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ * with the GNU Classpath Exception which is available at
12
+ * https://www.gnu.org/software/classpath/license.html.
13
+ *
14
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ ********************************************************************************/
16
+
17
+ import { ElementHandle } from '@playwright/test';
18
+ import { TheiaApp } from './theia-app';
19
+ import { TheiaDialog } from './theia-dialog';
20
+ import { TheiaMenuItem } from './theia-menu-item';
21
+ import { TheiaRenameDialog } from './theia-rename-dialog';
22
+ import { TheiaTreeNode } from './theia-tree-node';
23
+ import { TheiaView } from './theia-view';
24
+ import { elementContainsClass, normalizeId } from './util';
25
+
26
+ const TheiaExplorerViewData = {
27
+ tabSelector: '#shell-tab-explorer-view-container',
28
+ viewSelector: '#explorer-view-container--files',
29
+ viewName: 'Explorer'
30
+ };
31
+
32
+ export class TheiaExplorerFileStatNode extends TheiaTreeNode {
33
+
34
+ constructor(protected elementHandle: ElementHandle<SVGElement | HTMLElement>, protected explorerView: TheiaExplorerView) {
35
+ super(elementHandle, explorerView.app);
36
+ }
37
+
38
+ async absolutePath(): Promise<string | null> {
39
+ return this.elementHandle.getAttribute('title');
40
+ }
41
+
42
+ async isFile(): Promise<boolean> {
43
+ return ! await this.isFolder();
44
+ }
45
+
46
+ async isFolder(): Promise<boolean> {
47
+ return elementContainsClass(this.elementHandle, 'theia-DirNode');
48
+ }
49
+
50
+ async getMenuItemByNamePath(...names: string[]): Promise<TheiaMenuItem> {
51
+ const contextMenu = await this.openContextMenu();
52
+ const menuItem = await contextMenu.menuItemByNamePath(...names);
53
+ if (!menuItem) { throw Error('MenuItem could not be retrieved by path'); }
54
+ return menuItem;
55
+ }
56
+
57
+ }
58
+
59
+ export type TheiaExplorerFileStatNodePredicate = (node: TheiaExplorerFileStatNode) => Promise<boolean>;
60
+ export const DOT_FILES_FILTER: TheiaExplorerFileStatNodePredicate = async node => {
61
+ const label = await node.label();
62
+ return label ? !label.startsWith('.') : true;
63
+ };
64
+
65
+ export class TheiaExplorerView extends TheiaView {
66
+
67
+ constructor(public app: TheiaApp) {
68
+ super(TheiaExplorerViewData, app);
69
+ }
70
+
71
+ async activate(): Promise<void> {
72
+ await super.activate();
73
+ const viewElement = await this.viewElement();
74
+ await viewElement?.waitForSelector('.theia-TreeContainer');
75
+ }
76
+
77
+ async refresh(): Promise<void> {
78
+ await this.clickButton('__explorer-view-container_title:navigator.refresh');
79
+ }
80
+
81
+ async collapseAll(): Promise<void> {
82
+ await this.clickButton('__explorer-view-container_title:navigator.collapse.all');
83
+ }
84
+
85
+ protected async clickButton(id: string): Promise<void> {
86
+ await this.activate();
87
+ const viewElement = await this.viewElement();
88
+ const button = await viewElement?.waitForSelector(`#${normalizeId(id)}`);
89
+ await button?.click();
90
+ }
91
+
92
+ async visibleFileStatNodes(filterPredicate: TheiaExplorerFileStatNodePredicate = (_ => Promise.resolve(true))): Promise<TheiaExplorerFileStatNode[]> {
93
+ const viewElement = await this.viewElement();
94
+ const handles = await viewElement?.$$('.theia-FileStatNode');
95
+ if (handles) {
96
+ const nodes = handles.map(handle => new TheiaExplorerFileStatNode(handle, this));
97
+ const filteredNodes = [];
98
+ for (const node of nodes) {
99
+ if ((await filterPredicate(node)) === true) {
100
+ filteredNodes.push(node);
101
+ }
102
+ }
103
+ return filteredNodes;
104
+ }
105
+ return [];
106
+ }
107
+
108
+ async getFileStatNodeByLabel(label: string): Promise<TheiaExplorerFileStatNode> {
109
+ const file = await this.fileStatNode(label);
110
+ if (!file) { throw Error('File stat node could not be retrieved by path fragments'); }
111
+ return file;
112
+ }
113
+
114
+ async fileStatNode(filePath: string): Promise<TheiaExplorerFileStatNode | undefined> {
115
+ return this.fileStatNodeBySegments(...filePath.split('/'));
116
+ }
117
+
118
+ async fileStatNodeBySegments(...pathFragments: string[]): Promise<TheiaExplorerFileStatNode | undefined> {
119
+ await super.activate();
120
+ const viewElement = await this.viewElement();
121
+
122
+ let currentTreeNode = undefined;
123
+ let fragmentsSoFar = '';
124
+ for (let index = 0; index < pathFragments.length; index++) {
125
+ const fragment = pathFragments[index];
126
+ fragmentsSoFar += index !== 0 ? '/' : '';
127
+ fragmentsSoFar += fragment;
128
+
129
+ const selector = this.treeNodeSelector(fragmentsSoFar);
130
+ const nextTreeNode = await viewElement?.waitForSelector(selector, { state: 'visible' });
131
+ if (!nextTreeNode) {
132
+ throw new Error(`Tree node '${selector}' not found in explorer`);
133
+ }
134
+ currentTreeNode = new TheiaExplorerFileStatNode(nextTreeNode, this);
135
+ if (index < pathFragments.length - 1 && await currentTreeNode.isCollapsed()) {
136
+ await currentTreeNode.expand();
137
+ }
138
+ }
139
+
140
+ return currentTreeNode;
141
+ }
142
+
143
+ async selectTreeNode(filePath: string): Promise<void> {
144
+ await this.activate();
145
+ const treeNode = await this.page.waitForSelector(this.treeNodeSelector(filePath));
146
+ if (await this.isTreeNodeSelected(filePath)) {
147
+ await treeNode.focus();
148
+ } else {
149
+ await treeNode.click({ modifiers: ['Control'] });
150
+ }
151
+ }
152
+
153
+ async isTreeNodeSelected(filePath: string): Promise<boolean> {
154
+ const treeNode = await this.page.waitForSelector(this.treeNodeSelector(filePath));
155
+ return elementContainsClass(treeNode, 'theia-mod-selected');
156
+ }
157
+
158
+ protected treeNodeSelector(filePath: string): string {
159
+ return `.theia-FileStatNode:has(#${normalizeId(this.treeNodeId(filePath))})`;
160
+ }
161
+
162
+ protected treeNodeId(filePath: string): string {
163
+ const workspacePath = this.app.workspace.path;
164
+ return `${workspacePath}:${workspacePath}/${filePath}`;
165
+ }
166
+
167
+ async clickContextMenuItem(file: string, path: string[]): Promise<void> {
168
+ await this.activate();
169
+ const fileStatNode = await this.fileStatNode(file);
170
+ if (!fileStatNode) { throw Error('File stat node could not be retrieved by path fragments'); }
171
+ const menuItem = await fileStatNode.getMenuItemByNamePath(...path);
172
+ await menuItem.click();
173
+ }
174
+
175
+ protected async existsNode(path: string, isDirectory: boolean): Promise<boolean> {
176
+ const fileStatNode = await this.fileStatNode(path);
177
+ if (!fileStatNode) {
178
+ return false;
179
+ }
180
+ if (isDirectory) {
181
+ if (!await fileStatNode.isFolder()) {
182
+ throw Error(`FileStatNode for '${path}' is not a directory!`);
183
+ }
184
+ } else {
185
+ if (!await fileStatNode.isFile()) {
186
+ throw Error(`FileStatNode for '${path}' is not a file!`);
187
+ }
188
+ }
189
+ return true;
190
+ }
191
+
192
+ async existsFileNode(path: string): Promise<boolean> {
193
+ return this.existsNode(path, false);
194
+ }
195
+
196
+ async existsDirectoryNode(path: string): Promise<boolean> {
197
+ return this.existsNode(path, true);
198
+ }
199
+
200
+ async getNumberOfVisibleNodes(): Promise<number> {
201
+ await this.activate();
202
+ await this.app.quickCommandPalette.type('Refresh in Explorer');
203
+ await this.app.quickCommandPalette.trigger('File: Refresh in Explorer');
204
+ const fileStatElements = await this.visibleFileStatNodes(DOT_FILES_FILTER);
205
+ return fileStatElements.length;
206
+ }
207
+
208
+ async deleteNode(path: string, confirm = true): Promise<void> {
209
+ await this.activate();
210
+ await this.clickContextMenuItem(path, ['Delete']);
211
+
212
+ const confirmDialog = new TheiaDialog(this.app);
213
+ await confirmDialog.waitForVisible();
214
+ confirm ? await confirmDialog.clickMainButton() : await confirmDialog.clickSecondaryButton();
215
+ await confirmDialog.waitForClosed();
216
+ }
217
+
218
+ async renameNode(path: string, newName: string, confirm = true): Promise<void> {
219
+ await this.activate();
220
+ await this.clickContextMenuItem(path, ['Rename']);
221
+
222
+ const renameDialog = new TheiaRenameDialog(this.app);
223
+ await renameDialog.waitForVisible();
224
+ await renameDialog.enterNewName(newName);
225
+ confirm ? await renameDialog.confirm() : await renameDialog.close();
226
+ await renameDialog.waitForClosed();
227
+ }
228
+
229
+ }
@@ -0,0 +1,54 @@
1
+ /********************************************************************************
2
+ * Copyright (C) 2021 logi.cals GmbH, EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the Eclipse Public License v. 2.0 which is available at
6
+ * http://www.eclipse.org/legal/epl-2.0.
7
+ *
8
+ * This Source Code may also be made available under the following Secondary
9
+ * Licenses when the conditions for such availability set forth in the Eclipse
10
+ * Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ * with the GNU Classpath Exception which is available at
12
+ * https://www.gnu.org/software/classpath/license.html.
13
+ *
14
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ ********************************************************************************/
16
+
17
+ import { ElementHandle } from '@playwright/test';
18
+
19
+ import { TheiaMenu } from './theia-menu';
20
+ import { TheiaPageObject } from './theia-page-object';
21
+ import { normalizeId, toTextContentArray } from './util';
22
+
23
+ export class TheiaMainMenu extends TheiaMenu {
24
+ selector = '.p-Menu.p-MenuBar-menu';
25
+ }
26
+
27
+ export class TheiaMenuBar extends TheiaPageObject {
28
+
29
+ async openMenu(menuName: string): Promise<TheiaMainMenu> {
30
+ const menuBarItem = await this.menuBarItem(menuName);
31
+ const mainMenu = new TheiaMainMenu(this.app);
32
+ if (await mainMenu.isOpen()) {
33
+ await menuBarItem?.hover();
34
+ } else {
35
+ await menuBarItem?.click();
36
+ }
37
+ mainMenu.waitForVisible();
38
+ return mainMenu;
39
+ }
40
+
41
+ async visibleMenuBarItems(): Promise<string[]> {
42
+ const items = await this.page.$$(this.menuBarItemSelector());
43
+ return toTextContentArray(items);
44
+ }
45
+
46
+ protected menuBarItem(label = ''): Promise<ElementHandle<SVGElement | HTMLElement> | null> {
47
+ return this.page.waitForSelector(this.menuBarItemSelector(label));
48
+ }
49
+
50
+ protected menuBarItemSelector(label = ''): string {
51
+ return `${normalizeId('#theia:menubar')} .p-MenuBar-itemLabel >> text=${label}`;
52
+ }
53
+
54
+ }
@@ -0,0 +1,62 @@
1
+ /********************************************************************************
2
+ * Copyright (C) 2021 logi.cals GmbH, EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the Eclipse Public License v. 2.0 which is available at
6
+ * http://www.eclipse.org/legal/epl-2.0.
7
+ *
8
+ * This Source Code may also be made available under the following Secondary
9
+ * Licenses when the conditions for such availability set forth in the Eclipse
10
+ * Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ * with the GNU Classpath Exception which is available at
12
+ * https://www.gnu.org/software/classpath/license.html.
13
+ *
14
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ ********************************************************************************/
16
+
17
+ import { ElementHandle } from '@playwright/test';
18
+
19
+ import { textContent } from './util';
20
+
21
+ export class TheiaMenuItem {
22
+
23
+ constructor(protected element: ElementHandle<SVGElement | HTMLElement>) { }
24
+
25
+ protected labelElementHandle(): Promise<ElementHandle<SVGElement | HTMLElement>> {
26
+ return this.element.waitForSelector('.p-Menu-itemLabel');
27
+ }
28
+
29
+ protected shortCutElementHandle(): Promise<ElementHandle<SVGElement | HTMLElement>> {
30
+ return this.element.waitForSelector('.p-Menu-itemShortcut');
31
+ }
32
+
33
+ async label(): Promise<string | undefined> {
34
+ return textContent(this.labelElementHandle());
35
+ }
36
+
37
+ async shortCut(): Promise<string | undefined> {
38
+ return textContent(this.shortCutElementHandle());
39
+ }
40
+
41
+ async hasSubmenu(): Promise<boolean> {
42
+ return (await this.element.getAttribute('data-type')) === 'submenu';
43
+ }
44
+
45
+ async isEnabled(): Promise<boolean> {
46
+ const classAttribute = (await this.element.getAttribute('class'));
47
+ if (classAttribute === undefined || classAttribute === null) {
48
+ return false;
49
+ }
50
+ return !classAttribute.includes('p-mod-disabled');
51
+ }
52
+
53
+ async click(): Promise<void> {
54
+ return this.element.waitForSelector('.p-Menu-itemLabel')
55
+ .then(labelElement => labelElement.click({ position: { x: 10, y: 10 } }));
56
+ }
57
+
58
+ async hover(): Promise<void> {
59
+ return this.element.hover();
60
+ }
61
+
62
+ }
@@ -0,0 +1,96 @@
1
+ /********************************************************************************
2
+ * Copyright (C) 2021 logi.cals GmbH, EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the Eclipse Public License v. 2.0 which is available at
6
+ * http://www.eclipse.org/legal/epl-2.0.
7
+ *
8
+ * This Source Code may also be made available under the following Secondary
9
+ * Licenses when the conditions for such availability set forth in the Eclipse
10
+ * Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ * with the GNU Classpath Exception which is available at
12
+ * https://www.gnu.org/software/classpath/license.html.
13
+ *
14
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ ********************************************************************************/
16
+
17
+ import { ElementHandle } from '@playwright/test';
18
+
19
+ import { TheiaMenuItem } from './theia-menu-item';
20
+ import { TheiaPageObject } from './theia-page-object';
21
+ import { isDefined } from './util';
22
+
23
+ export class TheiaMenu extends TheiaPageObject {
24
+
25
+ selector = '.p-Menu';
26
+
27
+ protected async menuElementHandle(): Promise<ElementHandle<SVGElement | HTMLElement> | null> {
28
+ return this.page.$(this.selector);
29
+ }
30
+
31
+ async waitForVisible(): Promise<void> {
32
+ await this.page.waitForSelector(this.selector, { state: 'visible' });
33
+ }
34
+
35
+ async isOpen(): Promise<boolean> {
36
+ const menu = await this.menuElementHandle();
37
+ return !!menu && menu.isVisible();
38
+ }
39
+
40
+ async close(): Promise<void> {
41
+ if (!await this.isOpen()) {
42
+ return;
43
+ }
44
+ await this.page.mouse.click(0, 0);
45
+ await this.page.waitForSelector(this.selector, { state: 'detached' });
46
+ }
47
+
48
+ async menuItems(): Promise<TheiaMenuItem[]> {
49
+ const menuHandle = await this.menuElementHandle();
50
+ if (!menuHandle) {
51
+ return [];
52
+ }
53
+ const items = await menuHandle.$$('.p-Menu-content .p-Menu-item');
54
+ return items.map(element => new TheiaMenuItem(element));
55
+ }
56
+
57
+ async clickMenuItem(name: string): Promise<void> {
58
+ return (await this.page.waitForSelector(this.menuItemSelector(name))).click();
59
+ }
60
+
61
+ async menuItemByName(name: string): Promise<TheiaMenuItem | undefined> {
62
+ const menuItems = await this.menuItems();
63
+ for (const item of menuItems) {
64
+ const label = await item.label();
65
+ if (label === name) {
66
+ return item;
67
+ }
68
+ }
69
+ return undefined;
70
+ }
71
+
72
+ async menuItemByNamePath(...names: string[]): Promise<TheiaMenuItem | undefined> {
73
+ let item;
74
+ for (let index = 0; index < names.length; index++) {
75
+ item = await this.page.waitForSelector(this.menuItemSelector(names[index]), { state: 'visible' });
76
+ await item.hover();
77
+ }
78
+
79
+ const menuItemHandle = await item?.$('xpath=..');
80
+ if (menuItemHandle) {
81
+ return new TheiaMenuItem(menuItemHandle);
82
+ }
83
+ return undefined;
84
+ }
85
+
86
+ protected menuItemSelector(label = ''): string {
87
+ return `.p-Menu-content .p-Menu-itemLabel >> text=${label}`;
88
+ }
89
+
90
+ async visibleMenuItems(): Promise<string[]> {
91
+ const menuItems = await this.menuItems();
92
+ const labels = await Promise.all(menuItems.map(item => item.label()));
93
+ return labels.filter(isDefined);
94
+ }
95
+
96
+ }
@@ -0,0 +1,49 @@
1
+ /********************************************************************************
2
+ * Copyright (C) 2021 logi.cals GmbH, EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the Eclipse Public License v. 2.0 which is available at
6
+ * http://www.eclipse.org/legal/epl-2.0.
7
+ *
8
+ * This Source Code may also be made available under the following Secondary
9
+ * Licenses when the conditions for such availability set forth in the Eclipse
10
+ * Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ * with the GNU Classpath Exception which is available at
12
+ * https://www.gnu.org/software/classpath/license.html.
13
+ *
14
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ ********************************************************************************/
16
+
17
+ import { TheiaStatusIndicator } from './theia-status-indicator';
18
+
19
+ const NOTIFICATION_ICON = 'codicon-bell';
20
+ const NOTIFICATION_DOT_ICON = 'codicon-bell-dot';
21
+ const NOTIFICATION_ICONS = [NOTIFICATION_ICON, NOTIFICATION_DOT_ICON];
22
+
23
+ export class TheiaNotificationIndicator extends TheiaStatusIndicator {
24
+
25
+ protected get title(): string {
26
+ return 'Notification';
27
+ }
28
+
29
+ async isVisible(): Promise<boolean> {
30
+ return super.isVisible(NOTIFICATION_ICONS, this.title);
31
+ }
32
+
33
+ async hasNotifications(): Promise<boolean> {
34
+ return super.isVisible(NOTIFICATION_DOT_ICON, this.title);
35
+ }
36
+
37
+ async waitForVisible(expectNotifications = false): Promise<void> {
38
+ await super.waitForVisibleByIcon(expectNotifications ? NOTIFICATION_DOT_ICON : NOTIFICATION_ICON);
39
+ }
40
+
41
+ async toggleOverlay(): Promise<void> {
42
+ const hasNotifications = await this.hasNotifications();
43
+ const element = await this.getElementHandleByIcon(hasNotifications ? NOTIFICATION_DOT_ICON : NOTIFICATION_ICON, this.title);
44
+ if (element) {
45
+ await element.click();
46
+ }
47
+ }
48
+
49
+ }
@@ -0,0 +1,94 @@
1
+ /********************************************************************************
2
+ * Copyright (C) 2021 logi.cals GmbH, EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the Eclipse Public License v. 2.0 which is available at
6
+ * http://www.eclipse.org/legal/epl-2.0.
7
+ *
8
+ * This Source Code may also be made available under the following Secondary
9
+ * Licenses when the conditions for such availability set forth in the Eclipse
10
+ * Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ * with the GNU Classpath Exception which is available at
12
+ * https://www.gnu.org/software/classpath/license.html.
13
+ *
14
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ ********************************************************************************/
16
+
17
+ import { TheiaApp } from './theia-app';
18
+ import { TheiaNotificationIndicator } from './theia-notification-indicator';
19
+ import { TheiaPageObject } from './theia-page-object';
20
+
21
+ export class TheiaNotificationOverlay extends TheiaPageObject {
22
+
23
+ protected readonly HEADER_NOTIFICATIONS = 'NOTIFICATIONS';
24
+ protected readonly HEADER_NO_NOTIFICATIONS = 'NO NEW NOTIFICATIONS';
25
+
26
+ constructor(public app: TheiaApp, protected notificationIndicator: TheiaNotificationIndicator) {
27
+ super(app);
28
+ }
29
+
30
+ protected get selector(): string {
31
+ return '.theia-notifications-overlay';
32
+ }
33
+
34
+ protected get containerSelector(): string {
35
+ return `${this.selector} .theia-notifications-container.theia-notification-center`;
36
+ }
37
+
38
+ protected get titleSelector(): string {
39
+ return `${this.containerSelector} .theia-notification-center-header-title`;
40
+ }
41
+
42
+ async isVisible(): Promise<boolean> {
43
+ const element = await this.page.$(`${this.containerSelector}.open`);
44
+ return element ? element.isVisible() : false;
45
+ }
46
+
47
+ async waitForVisible(): Promise<void> {
48
+ await this.page.waitForSelector(`${this.containerSelector}.open`);
49
+ }
50
+
51
+ async activate(): Promise<void> {
52
+ if (!await this.isVisible()) {
53
+ await this.notificationIndicator.toggleOverlay();
54
+ }
55
+ await this.waitForVisible();
56
+ }
57
+
58
+ async toggle(): Promise<void> {
59
+ await this.app.quickCommandPalette.type('Toggle Notifications');
60
+ await this.app.quickCommandPalette.trigger('Notifications: Toggle Notifications');
61
+ }
62
+
63
+ protected entrySelector(entryText: string): string {
64
+ return `${this.containerSelector} .theia-notification-message span:has-text("${entryText}")`;
65
+ }
66
+
67
+ async waitForEntry(entryText: string): Promise<void> {
68
+ await this.activate();
69
+ await this.page.waitForSelector(this.entrySelector(entryText));
70
+ }
71
+
72
+ async waitForEntryDetached(entryText: string): Promise<void> {
73
+ await this.activate();
74
+ await this.page.waitForSelector(this.entrySelector(entryText), { state: 'detached' });
75
+ }
76
+
77
+ async isEntryVisible(entryText: string): Promise<boolean> {
78
+ await this.activate();
79
+ const element = await this.page.$(this.entrySelector(entryText));
80
+ return !!element && element.isVisible();
81
+ }
82
+
83
+ protected get clearAllButtonSelector(): string {
84
+ return this.selector + ' .theia-notification-center-header ul > li.codicon.codicon-clear-all';
85
+ }
86
+
87
+ async clearAllNotifications(): Promise<void> {
88
+ await this.activate();
89
+ const element = await this.page.waitForSelector(this.clearAllButtonSelector);
90
+ await element.click();
91
+ await this.notificationIndicator.waitForVisible(false /* expectNotifications */);
92
+ }
93
+
94
+ }
@@ -0,0 +1,29 @@
1
+ /********************************************************************************
2
+ * Copyright (C) 2021 logi.cals GmbH, EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the Eclipse Public License v. 2.0 which is available at
6
+ * http://www.eclipse.org/legal/epl-2.0.
7
+ *
8
+ * This Source Code may also be made available under the following Secondary
9
+ * Licenses when the conditions for such availability set forth in the Eclipse
10
+ * Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ * with the GNU Classpath Exception which is available at
12
+ * https://www.gnu.org/software/classpath/license.html.
13
+ *
14
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ ********************************************************************************/
16
+
17
+ import { Page } from '@playwright/test';
18
+
19
+ import { TheiaApp } from './theia-app';
20
+
21
+ export abstract class TheiaPageObject {
22
+
23
+ constructor(public app: TheiaApp) { }
24
+
25
+ get page(): Page {
26
+ return this.app.page;
27
+ }
28
+
29
+ }