Skip to content

Commit 003b217

Browse files
author
Colin Grant
committed
Fix Playwright tests
1 parent 42d0058 commit 003b217

File tree

5 files changed

+28
-72
lines changed

5 files changed

+28
-72
lines changed

examples/playwright/src/theia-notification-indicator.ts

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,26 @@
1616

1717
import { TheiaStatusIndicator } from './theia-status-indicator';
1818

19-
const NOTIFICATION_ICON = 'codicon-bell';
2019
const NOTIFICATION_DOT_ICON = 'codicon-bell-dot';
21-
const NOTIFICATION_ICONS = [NOTIFICATION_ICON, NOTIFICATION_DOT_ICON];
2220

2321
export class TheiaNotificationIndicator extends TheiaStatusIndicator {
24-
25-
protected get title(): string {
26-
return 'Notification';
27-
}
28-
29-
override async isVisible(): Promise<boolean> {
30-
return super.isVisible(NOTIFICATION_ICONS, this.title);
31-
}
22+
id = 'theia-notification-center';
3223

3324
async hasNotifications(): Promise<boolean> {
34-
return super.isVisible(NOTIFICATION_DOT_ICON, this.title);
25+
const container = await this.getElementHandle();
26+
const bellWithDot = await container.$(`.${NOTIFICATION_DOT_ICON}`);
27+
return Boolean(bellWithDot?.isVisible());
3528
}
3629

3730
override async waitForVisible(expectNotifications = false): Promise<void> {
38-
await super.waitForVisibleByIcon(expectNotifications ? NOTIFICATION_DOT_ICON : NOTIFICATION_ICON);
31+
await super.waitForVisible();
32+
if (expectNotifications && !(await this.hasNotifications())) {
33+
throw new Error('No notifications when notifcations expected.');
34+
}
3935
}
4036

4137
async toggleOverlay(): Promise<void> {
42-
const hasNotifications = await this.hasNotifications();
43-
const element = await this.getElementHandleByIcon(hasNotifications ? NOTIFICATION_DOT_ICON : NOTIFICATION_ICON, this.title);
38+
const element = await this.getElementHandle();
4439
if (element) {
4540
await element.click();
4641
}

examples/playwright/src/theia-problem-indicator.ts

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,8 @@
1717
import { ElementHandle } from '@playwright/test';
1818
import { TheiaStatusIndicator } from './theia-status-indicator';
1919

20-
const PROBLEM_ICON = 'codicon-error';
21-
2220
export class TheiaProblemIndicator extends TheiaStatusIndicator {
23-
24-
override async isVisible(): Promise<boolean> {
25-
const handle = await super.getElementHandleByIcon(PROBLEM_ICON);
26-
return !!handle && handle.isVisible();
27-
}
21+
id = 'problem-marker-status';
2822

2923
async numberOfProblems(): Promise<number> {
3024
const spans = await this.getSpans();
@@ -37,8 +31,7 @@ export class TheiaProblemIndicator extends TheiaStatusIndicator {
3731
}
3832

3933
protected async getSpans(): Promise<ElementHandle[] | undefined> {
40-
const handle = await super.getElementHandleByIcon(PROBLEM_ICON);
34+
const handle = await this.getElementHandle();
4135
return handle?.$$('span');
4236
}
43-
4437
}

examples/playwright/src/theia-status-indicator.ts

Lines changed: 15 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -17,60 +17,31 @@
1717
import { ElementHandle } from '@playwright/test';
1818
import { TheiaPageObject } from './theia-page-object';
1919

20-
export class TheiaStatusIndicator extends TheiaPageObject {
20+
export abstract class TheiaStatusIndicator extends TheiaPageObject {
21+
protected abstract id: string;
2122

22-
protected elementSpanSelector = '#theia-statusBar .element span';
23+
protected statusBarElementSelector = '#theia-statusBar div.element';
2324

24-
protected async getElementHandle(): Promise<ElementHandle<SVGElement | HTMLElement> | null> {
25-
return this.page.$(this.elementSpanSelector);
25+
protected getSelectorForId(id: string): string {
26+
return `${this.statusBarElementSelector}#status-bar-${id}`;
2627
}
2728

28-
async waitForVisible(): Promise<void> {
29-
await this.page.waitForSelector(this.elementSpanSelector);
29+
async waitForVisible(waitForDetached = false): Promise<void> {
30+
await this.page.waitForSelector(this.getSelectorForId(this.id), waitForDetached ? { state: 'detached' } : {});
3031
}
3132

32-
protected getSelectorByTitle(title: string): string {
33-
return `.element[title="${title}"]`;
34-
}
35-
36-
async getElementHandleByTitle(title: string): Promise<ElementHandle<SVGElement | HTMLElement> | null> {
37-
// Fetch element via title in case status elements exist without a dedicated Codicon icon
38-
return this.page.$(this.getSelectorByTitle(title));
39-
}
40-
41-
protected getSelectorByIcon(icon: string): string {
42-
return `${this.elementSpanSelector}.codicon.${icon}`;
43-
}
44-
45-
async getElementHandleByIcon(iconClass: string | string[], titleContain = ''): Promise<ElementHandle<SVGElement | HTMLElement> | null> {
46-
const icons = Array.isArray(iconClass) ? iconClass : [iconClass];
47-
for (const icon of icons) {
48-
const span = await this.page.$(this.getSelectorByIcon(icon));
49-
if (span) {
50-
const parent = await span.$('..');
51-
if (titleContain === '') {
52-
return parent;
53-
} else {
54-
const parentTitle = await parent?.getAttribute('title');
55-
if (parentTitle?.includes(titleContain)) { return parent; }
56-
}
57-
}
33+
async getElementHandle(): Promise<ElementHandle<SVGElement | HTMLElement>> {
34+
const element = await this.page.$(this.getSelectorForId(this.id));
35+
if (element) {
36+
return element;
5837
}
59-
throw new Error('Cannot find indicator');
60-
}
61-
62-
async waitForVisibleByTitle(title: string, waitForDetached = false): Promise<void> {
63-
await this.page.waitForSelector(this.getSelectorByTitle(title), waitForDetached ? { state: 'detached' } : {});
64-
}
65-
66-
async waitForVisibleByIcon(icon: string, waitForDetached = false): Promise<void> {
67-
await this.page.waitForSelector(this.getSelectorByIcon(icon), waitForDetached ? { state: 'detached' } : {});
38+
throw new Error('Could not find status bar element with ID ' + this.id);
6839
}
6940

70-
async isVisible(icon: string | string[], titleContain = ''): Promise<boolean> {
41+
async isVisible(): Promise<boolean> {
7142
try {
72-
const element = await this.getElementHandleByIcon(icon, titleContain);
73-
return !!element && element.isVisible();
43+
const element = await this.getElementHandle();
44+
return element.isVisible();
7445
} catch (err) {
7546
return false;
7647
}

examples/playwright/src/theia-toggle-bottom-indicator.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@
1616

1717
import { TheiaStatusIndicator } from './theia-status-indicator';
1818

19-
const TOGGLE_BOTTOM_ICON = 'codicon-window';
20-
2119
export class TheiaToggleBottomIndicator extends TheiaStatusIndicator {
22-
override async isVisible(): Promise<boolean> {
23-
return super.isVisible(TOGGLE_BOTTOM_ICON);
24-
}
20+
id = 'bottom-panel-toggle';
2521
}

packages/core/src/browser/status-bar/status-bar.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ export class StatusBarImpl extends ReactWidget implements StatusBar {
120120
protected createAttributes(viewEntry: StatusBarViewEntry): React.Attributes & React.HTMLAttributes<HTMLElement> {
121121
const attrs: React.Attributes & React.HTMLAttributes<HTMLElement> = {};
122122
const entry = viewEntry.entry;
123+
attrs.id = 'status-bar-' + viewEntry.id;
123124
attrs.className = 'element';
124125
if (entry.command || entry.onclick || entry.tooltip) {
125126
attrs.className += ' hasCommand';

0 commit comments

Comments
 (0)