Skip to content

Commit 50af8ab

Browse files
authored
test: DH-20440: DHE e2e tests - Support for grizzly servers (#282)
DH-20440: DHE e2e tests - support for testing grizzly servers from local machine. - Creates settings for given server > Note: only supports grizzly servers that only have basic login configured. Follow up PRs to add support for: > - selecting auth type > - worker creation dialog required for gplus > - CI ### Testing - Checkout this PR - npm i - Run tests ```sh npm run test:e2e -- --coreplus https://qa-grizzly-java17-cluster-infra-1.int.illumon.com:8000/ ```
1 parent 17b79db commit 50af8ab

File tree

15 files changed

+3250
-1624
lines changed

15 files changed

+3250
-1624
lines changed

.github/workflows/e2e.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
cache: 'npm'
1919
- run: npm ci
2020
- name: Run end-to-end tests
21-
run: xvfb-run npm run test:e2e
21+
run: xvfb-run npm run test:e2e:docker
2222
- name: Upload Screenshots as Artifact
2323
if: ${{ always() }}
2424
uses: actions/upload-artifact@v4

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ node_modules
66
.DS_Store
77
e2e-testing/.resources
88
e2e-testing/.test-extensions
9+
e2e-testing/test-ws/.vscode/settings.json
910
test-reports/
1011
tsconfig.tsbuildinfo
1112
.env*.local

e2e-testing/src/mocharc.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@ import { MochaOptions } from 'vscode-extension-tester';
22

33
const options: MochaOptions = {
44
timeout: 30000,
5-
reporter: 'mocha-ctrf-json-reporter',
5+
slow: 20000,
6+
reporter: 'mocha-multi-reporters',
67
reporterOptions: {
7-
outputDir: 'test-reports',
8+
reporterEnabled: 'spec, mocha-ctrf-json-reporter',
9+
mochaCtrfJsonReporterReporterOptions: {
10+
outputDir: 'test-reports',
11+
},
812
},
913
};
1014

e2e-testing/src/pageObjects/EditorViewExtended.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ export class EditorViewExtended extends EditorView {
182182

183183
await tab.select();
184184

185-
return new WebViewExtended(group).wait();
185+
return new WebViewExtended(group).waitForStable();
186186
}
187187

188188
/**

e2e-testing/src/specs/panels.spec.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { Workbench } from 'vscode-extension-tester';
21
import { EditorViewExtended } from '../pageObjects';
32
import {
3+
connectToServer,
4+
executeCommandWithRetry,
45
expectDeepEqualArray,
5-
openFileResources,
66
runDhFileCodeLens,
77
setup,
88
SIMPLE_TICKING3_PY,
@@ -50,10 +50,9 @@ const expectedTabs = {
5050

5151
describe('Panels Tests', () => {
5252
before(async () => {
53-
const explorerView = await setup();
54-
await openFileResources(SIMPLE_TICKING3_PY.path);
55-
await explorerView?.closeView();
56-
await new Workbench().executeCommand('View: Split Editor Down');
53+
await setup(SIMPLE_TICKING3_PY.path);
54+
await connectToServer();
55+
await executeCommandWithRetry('View: Split Editor Down');
5756
});
5857

5958
after(async () => {
@@ -207,7 +206,7 @@ describe('Panels Tests', () => {
207206
await step(7, 'Move tab to new group', async stepLabel => {
208207
await editorView.openWebView('t3', 2);
209208

210-
await new Workbench().executeCommand('View: Move Editor into Next Group');
209+
await executeCommandWithRetry('View: Move Editor into Next Group');
211210

212211
const editorGroupsData = await editorView.getEditorGroupsData();
213212
expectDeepEqualArray(

e2e-testing/src/specs/statusBar.spec.ts

Lines changed: 18 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,33 @@
1+
import { InputBox } from 'vscode-extension-tester';
12
import {
2-
InputBox,
3-
QuickPickItem,
4-
StatusBar,
5-
VSBrowser,
6-
} from 'vscode-extension-tester';
7-
import {
3+
getDhStatusBarItem,
4+
getServerItems,
85
getSidebarViewItem,
9-
openFileResources,
106
setup,
117
SIMPLE_TICKING3_PY,
128
SIMPLE_TICKING_MD,
139
step,
1410
teardown,
1511
TEST_GROOVY,
1612
TEST_TXT,
13+
waitForServerConnection,
1714
} from '../util';
1815
import { EditorViewExtended } from '../pageObjects';
1916
import { assert } from 'chai';
20-
import { SERVER_TITLE, STATUS_BAR_TITLE, VIEW_NAME } from '../util/constants';
17+
import { VIEW_NAME } from '../util/constants';
2118

2219
describe('Status Bar Tests', () => {
2320
let editorView: EditorViewExtended;
24-
let statusBar: StatusBar;
2521

2622
before(async () => {
27-
const explorerView = await setup();
28-
29-
await openFileResources(
23+
await setup(
3024
SIMPLE_TICKING_MD.path,
3125
SIMPLE_TICKING3_PY.path,
3226
TEST_GROOVY.path,
3327
TEST_TXT.path
3428
);
3529

36-
await explorerView?.closeView();
37-
3830
editorView = new EditorViewExtended();
39-
statusBar = new StatusBar();
4031
});
4132

4233
after(async () => {
@@ -55,14 +46,12 @@ describe('Status Bar Tests', () => {
5546
] as const) {
5647
await step(s, fileName, async stepLabel => {
5748
await editorView.openTextEditor(fileName);
58-
const statusBarItem = await statusBar.getItem(
59-
'plug Deephaven: Disconnected'
60-
);
49+
const statusBarItem = await getDhStatusBarItem();
6150

6251
if (isVisible) {
63-
assert.isDefined(statusBarItem, stepLabel);
52+
assert.isNotNull(statusBarItem, stepLabel);
6453
} else {
65-
assert.isUndefined(statusBarItem, stepLabel);
54+
assert.isNull(statusBarItem, stepLabel);
6655
}
6756
});
6857
}
@@ -71,41 +60,26 @@ describe('Status Bar Tests', () => {
7160
it('should connect to server on click', async () => {
7261
await editorView.openTextEditor(SIMPLE_TICKING3_PY.name);
7362

74-
await step(1, 'Click Deephaven status bar item', async () => {
75-
const statusBarItem = await statusBar.getItem(
76-
STATUS_BAR_TITLE.disconnected
77-
);
78-
assert.isDefined(statusBarItem);
63+
await step(1, 'Click Deephaven status bar item', async stepLabel => {
64+
const statusBarItem = await getDhStatusBarItem();
65+
assert.isNotNull(statusBarItem, stepLabel);
7966
await statusBarItem.click();
8067
});
8168

8269
await step(2, 'Select connection', async () => {
8370
const input = await InputBox.create();
84-
const qpItem = new QuickPickItem(0, input);
85-
await qpItem.click();
71+
await input.selectQuickPick(0);
8672

87-
// We could call `ViewControl.openView` to ensure DH view is opened, but we
88-
// want to test it opens automatically when a connection is initiated. The
89-
// 500ms sleep matches the timeout that `ViewControl.openView` uses but
90-
// without attempting to open the view.
91-
await VSBrowser.instance.driver.sleep(500);
73+
await waitForServerConnection();
9274
});
9375

94-
step(3, 'Verify server node', async stepLabel => {
95-
const localhost1000Item = await getSidebarViewItem(
96-
VIEW_NAME.servers,
97-
SERVER_TITLE
98-
);
76+
await step(3, 'Verify server node', async stepLabel => {
77+
const [serverItem] = await getServerItems();
9978

100-
assert.isDefined(localhost1000Item, stepLabel);
101-
assert.equal(
102-
await localhost1000Item.getText(),
103-
`${SERVER_TITLE}(1)`,
104-
stepLabel
105-
);
79+
assert.isDefined(serverItem, stepLabel);
10680
});
10781

108-
step(4, 'Verify connection node', async stepLabel => {
82+
await step(4, 'Verify connection node', async stepLabel => {
10983
const simpleTickingEditor = await getSidebarViewItem(
11084
VIEW_NAME.connections,
11185
SIMPLE_TICKING3_PY.name

e2e-testing/src/util/constants.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
export const SERVER_TITLE = 'localhost:10000';
2-
31
export const STATUS_BAR_TITLE = {
2+
connectedPrefix: 'vm-connect DHC:',
43
disconnected: 'plug Deephaven: Disconnected',
54
} as const;
65

e2e-testing/src/util/lifeCycle.ts

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,34 @@
1+
import { EditorView } from 'vscode-extension-tester';
12
import {
2-
ActivityBar,
3-
EditorView,
4-
type ViewControl,
5-
} from 'vscode-extension-tester';
6-
import { disconnectFromServer, getElementOrNull } from './testUtils';
7-
import { SERVER_TITLE } from './constants';
3+
getElementOrNull,
4+
openFileResources,
5+
openActivityBarView,
6+
disconnectFromServers,
7+
closeActivityBarView,
8+
} from './testUtils';
89
import { locators } from './locators';
910

1011
/**
1112
* Setup before running test suite.
1213
*/
13-
export async function setup(): Promise<ViewControl | undefined> {
14-
const chatCloseButton = await getElementOrNull(locators.chatCloseButton);
15-
await chatCloseButton?.click();
14+
export async function setup(
15+
...initialFilePaths: [string, ...string[]]
16+
): Promise<void> {
17+
try {
18+
const chatCloseButton = await getElementOrNull(locators.chatCloseButton);
19+
await chatCloseButton?.click();
20+
} catch {
21+
// Chat button not found or not interactable - continue anyway
22+
}
1623

17-
const explorer = await new ActivityBar().getViewControl('Explorer');
24+
// Need to open a file before login since an active editor is required for
25+
// Deephaven: Select Connection command to work
26+
await openFileResources(...initialFilePaths);
1827

19-
if (!(await explorer?.isSelected())) {
20-
await explorer?.openView();
21-
}
28+
// Ensure Deephaven extension is activated by opening the Deephaven view
29+
await openActivityBarView('Deephaven');
2230

23-
return explorer;
31+
await closeActivityBarView('Deephaven');
2432
}
2533

2634
/**
@@ -30,6 +38,9 @@ export async function teardown(): Promise<void> {
3038
await new EditorView().closeAllEditors();
3139

3240
try {
33-
await disconnectFromServer(SERVER_TITLE);
34-
} catch {}
41+
await disconnectFromServers();
42+
} catch (err) {
43+
// eslint-disable-next-line no-console
44+
console.error('Error during disconnectFromServers:', err);
45+
}
3546
}

e2e-testing/src/util/locators.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import { By } from 'vscode-extension-tester';
22

33
export const locators = {
4+
/** Locator for an active connection icon */
5+
activeConnection: By.css(
6+
'.custom-view-tree-node-item-icon.codicon.codicon-vm-connect'
7+
),
8+
49
/**
510
* Locator for side panel close button so we can close the Copilot chat. Note
611
* that the button is always present, but parent div gets `empty` class when
@@ -10,6 +15,11 @@ export const locators = {
1015
'.auxiliarybar:not(.empty) a[aria-label^="Hide Secondary Side Bar"]'
1116
),
1217

18+
/** Locator for a connected server icon */
19+
connectedServerIcon: By.css(
20+
'.custom-view-tree-node-item-icon.codicon.codicon-circle-large-filled'
21+
),
22+
1323
irisGrid: By.css('.iris-grid'),
1424

1525
/** Locator for the containing div of a WebView */

0 commit comments

Comments
 (0)