Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tests for debugging a Quarkus application #223

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,19 @@ branches:

before_install:
- if [ $TRAVIS_OS_NAME == "linux" ]; then
sudo apt-get -y install libxtst-dev;
sudo apt-get -y install libxtst-dev libsecret-1-dev;
fi
- if [ $TRAVIS_OS_NAME == "osx" ]; then
nvm install 12.12;
fi
- npm install -g vsce
- cd ..
- git clone https://github.com/redhat-developer/quarkus-ls
- cd vscode-quarkus

install:
- npm install
- npm i
- npm run build
- npm run vscode:prepublish
- vsce package

Expand Down
7 changes: 5 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,8 @@ This script does two things.
`vscode-quarkus/jars/`.

In addition to `npm run build`, there are two more build scripts:
`npm run build-server` only builds the Quarkus language server and places the jar in `vscode-quarkus/server/`.
`npm run build-ext` only builds the Quarkus jdt.ls extension and places the jar in `vscode-quarkus/jars/`.
`npm run build-server` only builds the MicroProfile language server and places the jar in `vscode-quarkus/server/`.
`npm run build-ext` only builds the MicroProfile jdt.ls extension and places the jar in `vscode-quarkus/jars/`.

### Running vscode-quarkus
**Step 1.** Open `vscode-quarkus/` in VSCode.
Expand Down Expand Up @@ -294,6 +294,9 @@ When running the UI tests, it would be best to disable all other VS Code extensi
so that they don't interfere during the testing. Also, please be sure to not do anything else with your machine. Its very important to not disturb your machine when running the UI tests, or
else the test functions will not run properly.

Additionally, please finish the [Setup](#setup) steps before running the UI tests.
The setup is important because the debugging tests require the MicroProfile jdt.ls extension.

**Note for running UI tests of macOS:**
Due to an issue for an upstream UI testing library:
[nut-tree/nut.js#98 (issue)](https://github.com/nut-tree/nut.js/issues/98#issuecomment-571494625), UI tests on macOS work as long as
Expand Down
804 changes: 592 additions & 212 deletions package-lock.json

Large diffs are not rendered by default.

11 changes: 9 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -342,33 +342,40 @@
"build-server": "./node_modules/.bin/gulp buildServer",
"build-ext": "./node_modules/.bin/gulp buildExtension",
"test-ui": "npm run test-compile && npm run test-ui-run",
"test-ui-run": "extest setup-and-run 'out/test/vscodeUiTest/suite/*.js' -u",
"test-ui-run": "extest setup-and-run 'out/test/vscodeUiTest/suite/**/tests/*Test.js' -u -o src/test/vscodeUiTest/settings.json -c 1.42.1",
"test-all": "npm test && npm run test-ui-run"
},
"devDependencies": {
"@types/chai": "^4.2.3",
"@types/chai-fs": "^2.0.2",
"@types/fs-extra": "^7.0.0",
"@types/hjson": "^2.4.1",
"@types/lodash": "^4.14.149",
"@types/mocha": "^5.2.6",
"@types/ncp": "^2.0.3",
"@types/node": "^10.14.16",
"@types/request": "^2.48.3",
"@types/request-promise": "^4.1.44",
"@types/rimraf": "^2.0.3",
"@types/semver": "^6.2.0",
"@types/vscode": "^1.37.0",
"@types/yauzl": "^2.9.1",
"chai": "^4.2.0",
"chai-fs": "^2.0.0",
"del": "^5.1.0",
"gradle-to-js": "^2.0.0",
"gulp": "^4.0.2",
"gulp-rename": "^1.4.0",
"hjson": "^3.2.1",
"mocha": "^6.2.1",
"ncp": "^2.0.0",
"pom-parser": "^1.2.0",
"rimraf": "^3.0.2",
"ts-loader": "^6.0.1",
"tslint": "^5.20.1",
"typescript": "^3.7.2",
"typescript-tslint-plugin": "^0.3.1",
"vscode-extension-tester": "^2.3.0",
"vscode-extension-tester": "^2.4.0",
"vscode-test": "^1.2.3",
"webpack": "^4.32.2",
"webpack-cli": "^3.3.2"
Expand Down
8 changes: 6 additions & 2 deletions src/test/vscodeUiTest/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,9 @@
*/
import { ExTester } from 'vscode-extension-tester';

const tester: ExTester = new ExTester();
tester.setupAndRunTests(undefined, undefined, 'out/test/vscodeUiTest/suite/*.js');
async function runTests() {
const tester: ExTester = new ExTester();
await tester.setupAndRunTests('1.42.1', undefined, 'out/test/vscodeUiTest/suite/**/tests/multiProjectMultiWorkspaceTest.js', 'src/test/vscodeUiTest/settings.json');
}

runTests();
4 changes: 4 additions & 0 deletions src/test/vscodeUiTest/log.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
const LOG_PROGRESS: boolean = false;
export function log(str: string) {
if (LOG_PROGRESS) console.log(str);
}
3 changes: 3 additions & 0 deletions src/test/vscodeUiTest/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"debug.onTaskErrors": "showErrors"
}
131 changes: 131 additions & 0 deletions src/test/vscodeUiTest/suite/debuggingTests/debugProjectInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/**
* Copyright 2020 Red Hat, Inc. and others.

* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at

* http://www.apache.org/licenses/LICENSE-2.0

* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

export class BuildSupportInfo {
private executable: string;
private wrapper: string;
private windowsWrapper: string;
private quarkusDev: string;
private commandParam: string | undefined;
constructor(
executable: string,
wrapper: string,
windowsWrapper: string,
quarkusDev: string,
commandParam?: string
) {
this.executable = executable;
this.wrapper = wrapper;
this.windowsWrapper = windowsWrapper;
this.quarkusDev = quarkusDev;
this.commandParam = commandParam;
}

public getExecutable(): string {
return this.executable;
}

public getWrapper(): string {
return this.wrapper;
}

public getWindowsWrapper(): string {
return this.windowsWrapper;
}

public getQuarkusDev(): string {
return this.quarkusDev;
}

public getCommand(options: { useWrapper: boolean }): string {
return this.addParamsIfNeeded(
`${options.useWrapper ? this.wrapper : this.executable} ${
this.quarkusDev
} `
);
}

public getWindowsCommand(options: { useWrapper: boolean }): string {
return this.addParamsIfNeeded(
`${options.useWrapper ? this.windowsWrapper : this.executable} ${
this.quarkusDev
} `
);
}

private addParamsIfNeeded(command: string): string {
return command + (this.commandParam ? this.commandParam : "");
}
}

export interface ProjectInfo {
projectName: string;
parentFolderName: string;
resourceClass: string;
message: string;
port: number;
buildSupport: BuildSupportInfo;
}

export const MAVEN: BuildSupportInfo = new BuildSupportInfo(
"mvn",
"./mvnw",
".\\mvnw.cmd",
"quarkus:dev"
);
export const GRADLE: BuildSupportInfo = new BuildSupportInfo(
"gradle",
"./gradlew",
".\\gradlew.bat",
"quarkusDev",
"--console=plain"
);

export const QUARKUS_MAVEN_1: ProjectInfo = {
projectName: "quarkus-maven-1",
parentFolderName: "maven-projects",
resourceClass: "QuarkusMaven1.java",
message: "hello from QuarkusMaven1",
port: 8080,
buildSupport: MAVEN
};

export const QUARKUS_MAVEN_2: ProjectInfo = {
projectName: "quarkus-maven-2",
parentFolderName: "maven-projects",
resourceClass: "QuarkusMaven2.java",
message: "hello from QuarkusMaven2",
port: 9090,
buildSupport: MAVEN
};

export const QUARKUS_GRADLE_1: ProjectInfo = {
projectName: "quarkus-gradle-1",
parentFolderName: "gradle-projects",
resourceClass: "QuarkusGradle1.java",
message: "hello from QuarkusGradle1",
port: 8080,
buildSupport: GRADLE
};

export const QUARKUS_GRADLE_2: ProjectInfo = {
projectName: "quarkus-gradle-2",
parentFolderName: "gradle-projects",
resourceClass: "QuarkusGradle2.java",
message: "hello from QuarkusGradle2",
port: 9090,
buildSupport: GRADLE
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/**
* Copyright 2020 Red Hat, Inc. and others.

* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at

* http://www.apache.org/licenses/LICENSE-2.0

* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as del from 'del';
import * as fs from 'fs-extra';
import * as path from 'path';
import { DialogHandler, OpenDialog, VSBrowser, WebDriver, Workbench } from 'vscode-extension-tester';
import { ProjectInfo, QUARKUS_GRADLE_1, QUARKUS_GRADLE_2, QUARKUS_MAVEN_1, QUARKUS_MAVEN_2 } from '../debugProjectInfo';
import { addFolder, assertDebugProjectWhenNoEditorsOpen, assertLaunchJson, assertTasksJson, copyToTempDir, LaunchConfigInfo, TaskInfo, TEST_PROJECTS_DIR, waitForQuarkusWelcomePage, WorkspaceInfo } from '../utils';

describe('Debug multiple project multiple workspace tests', function () {
this.bail(true);
this.retries(3);

let driver: WebDriver;
const tempDir: string = path.join(__dirname, 'temp');

before(() => {
driver = VSBrowser.instance.driver;
});

beforeEach(async function() {
this.timeout(10000);
await new Promise((res) => setTimeout(res, 3000));
if (fs.existsSync(tempDir)) {
await del(tempDir);
}
fs.mkdirSync(tempDir);
});

after(async function() {
this.timeout(10000);
if (fs.existsSync(tempDir)) {
await del(tempDir);
}
});

afterEach(async function() {
this.timeout(10000);
await VSBrowser.instance.waitForWorkbench();
await (new Workbench()).executeCommand('Clear Editor History');
await (new Workbench()).executeCommand('Close Workspace');
});

it('should debug Quarkus Maven projects in separate workspace folders', async function () {
this.timeout(300000);
await assertDebuggingTwoProjects(QUARKUS_MAVEN_1, QUARKUS_MAVEN_2);
});

it('should debug Quarkus Gradle projects in separate workspace folders', async function () {
this.timeout(300000);
await assertDebuggingTwoProjects(QUARKUS_GRADLE_1, QUARKUS_GRADLE_2);
});

async function setupWorkspace(project1: ProjectInfo, project2: ProjectInfo): Promise<WorkspaceInfo> {
const project1Dir: string = path.join(TEST_PROJECTS_DIR, project1.parentFolderName, project1.projectName);
const project2Dir: string = path.join(TEST_PROJECTS_DIR, project2.parentFolderName, project2.projectName);
const workspaceDir: string = path.join(TEST_PROJECTS_DIR, 'empty.code-workspace');
const tempProject1Dir: string = await copyToTempDir(project1Dir, tempDir);
const tempProject2Dir: string = await copyToTempDir(project2Dir, tempDir);
const tempWorkspace: string = await copyToTempDir(workspaceDir, tempDir);
await new Workbench().executeCommand('Workspaces: Open Workspace...');
const dialog: OpenDialog = await DialogHandler.getOpenDialog();
await dialog.selectPath(tempWorkspace);
await dialog.confirm();
await addFolder(path.join(tempProject1Dir));
await addFolder(path.join(tempProject2Dir));
return {
workspaceFolders: [tempProject1Dir, tempProject2Dir]
};
}

async function assertDebuggingTwoProjects(
project1: ProjectInfo,
project2: ProjectInfo
) {
const workspace: WorkspaceInfo = await setupWorkspace(project1, project2);
await waitForQuarkusWelcomePage(driver);
await new Workbench().executeCommand("View: Close All Editors"); // close welcome pages
await assertDebugProjectWhenNoEditorsOpen(driver, project1, {endPrematurely: false});
// await assertDebugProjectWhenProjectFileOpen(driver, project1, {endPrematurely: true});
await assertDebugProjectWhenNoEditorsOpen(driver, project2, {endPrematurely: false});
// await assertDebugProjectWhenProjectFileOpen(driver, project2, {endPrematurely: true});

assertTasksJson(workspace.workspaceFolders[0], [
expectedTask(project1, true)
]);
assertTasksJson(workspace.workspaceFolders[1], [
expectedTask(project2, true)
]);
assertLaunchJson(workspace.workspaceFolders[0], [
expectedLaunchConfig(project1)
]);
assertLaunchJson(workspace.workspaceFolders[1], [
expectedLaunchConfig(project1)
]);

// deleteLaunchAndTasksJson(workspace.workspaceFolders[0]);
// deleteLaunchAndTasksJson(workspace.workspaceFolders[1]);
// removeWrapperFiles(workspace.workspaceFolders[0], project1);
// removeWrapperFiles(workspace.workspaceFolders[1], project2);

// await assertDebugProjectWhenNoEditorsOpen(driver, project1, {endPrematurely: true});
// await assertDebugProjectWhenNoEditorsOpen(driver, project2, {endPrematurely: true});

// assertTasksJson(workspace.workspaceFolders[0], [
// expectedTask(project1, false)
// ]);
// assertTasksJson(workspace.workspaceFolders[1], [
// expectedTask(project2, false)
// ]);
// assertLaunchJson(workspace.workspaceFolders[0], [
// expectedLaunchConfig(project1)
// ]);
// assertLaunchJson(workspace.workspaceFolders[1], [
// expectedLaunchConfig(project2)
// ]);
}

function expectedTask(project: ProjectInfo, useWrapper: boolean): TaskInfo {
return {
label: project.buildSupport.getQuarkusDev(),
command: project.buildSupport.getCommand({ useWrapper }),
windowsCommand: project.buildSupport.getWindowsCommand({ useWrapper })
};
}

function expectedLaunchConfig(project: ProjectInfo): LaunchConfigInfo {
return {
preLaunchTask: `${project.buildSupport.getQuarkusDev()}`,
name: 'Debug Quarkus application'
};
}
});
Loading