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

Adapt testsuites of the Language server validation and build features for DevWorkspaceHappyPath #20476

Merged
merged 7 commits into from
Sep 21, 2021
170 changes: 160 additions & 10 deletions tests/e2e/tests/e2e_happy_path/DevWorkspaceHappyPath.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,35 +10,185 @@

import { e2eContainer } from '../../inversify.config';
import { CLASSES } from '../../inversify.types';
import { ProjectAndFileTests } from '../../testsLibrary/ProjectAndFileTests';
import CheReporter from '../../driver/CheReporter';
import { BrowserTabsUtil } from '../../utils/BrowserTabsUtil';
import { WorkspaceNameHandler } from '../../utils/WorkspaceNameHandler';
import { TestConstants } from '../../TestConstants';
import { Ide } from '../../pageobjects/ide/Ide';
import { TimeoutConstants } from '../../TimeoutConstants';
import { TopMenu } from '../../pageobjects/ide/TopMenu';
import { ProjectTree } from '../../pageobjects/ide/ProjectTree';
import { Editor } from '../../pageobjects/ide/Editor';
import { Key, error, By } from 'selenium-webdriver';
import { DriverHelper } from '../../utils/DriverHelper';
import { Logger } from '../../utils/Logger';
import { Terminal } from '../../pageobjects/ide/Terminal';
import { DialogWindow } from '../../pageobjects/ide/DialogWindow';
import * as fs from 'fs';

const projectAndFileTests: ProjectAndFileTests = e2eContainer.get(CLASSES.ProjectAndFileTests);
const ide: Ide = e2eContainer.get(CLASSES.Ide);
musienko-maxim marked this conversation as resolved.
Show resolved Hide resolved
const projectTree: ProjectTree = e2eContainer.get(CLASSES.ProjectTree);
const browserTabsUtil: BrowserTabsUtil = e2eContainer.get(CLASSES.BrowserTabsUtil);
const workspaceNameHandler: WorkspaceNameHandler = e2eContainer.get(CLASSES.WorkspaceNameHandler);
const projectName: string = 'java-spring-petclinic';
const workspaceRootFolderName: string = 'src';
const pathToJavaFolder: string = `${projectName}/${workspaceRootFolderName}/main/java/org/springframework/samples/petclinic`;
const javaFileName: string = 'PetClinicApplication.java';
const editor: Editor = e2eContainer.get(CLASSES.Editor);
const classPathFilename: string = '.classpath';
const driverHelper: DriverHelper = e2eContainer.get(CLASSES.DriverHelper);
const codeNavigationClassName: string = 'SpringApplication.class';
const topMenu: TopMenu = e2eContainer.get(CLASSES.TopMenu);
const globalTaskScope = 'Global';
const terminal: Terminal = e2eContainer.get(CLASSES.Terminal);
const warningDialog: DialogWindow = e2eContainer.get(CLASSES.DialogWindow);


const SpringAppLocators = {
springTitleLocator: By.xpath('//div[@class=\'container-fluid\']//h2[text()=\'Welcome\']'),
springMenuButtonLocator: By.css('button[data-target=\'#main-navbar\']'),
springErrorButtonLocator: By.xpath('//div[@id=\'main-navbar\']//span[text()=\'Error\']'),
springHomeButtonLocator: By.className('navbar-brand'),
springErrorMessageLocator: By.xpath(`//h2[text()='Something happened...']`)
};

// this test checks only workspace created from "web-nodejs-sample" https://github.com/devfile/devworkspace-operator/blob/main/samples/flattened_theia-next.yaml.
suite('Workspace creation via factory url', async () => {

let factoryUrl : string = `${TestConstants.TS_SELENIUM_DEVWORKSPACE_URL}`;
const workspaceSampleName: string = 'java-spring-petclinic';
const workspaceRootFolderName: string = 'src';

suite('Open factory URL', async () => {

test(`Navigating to factory URL`, async () => {
await browserTabsUtil.navigateTo(factoryUrl);
});
});

suite('Wait workspace readiness', async () => {
test('Register running workspace', async () => {
CheReporter.registerRunningWorkspace(await workspaceNameHandler.getNameFromUrl());
CheReporter.registerRunningWorkspace(projectName);
});

projectAndFileTests.waitWorkspaceReadiness(workspaceSampleName, workspaceRootFolderName);
test('Register running workspace', async () => {
await ide.waitAndSwitchToIdeFrame();
await ide.waitIde(TimeoutConstants.TS_SELENIUM_START_WORKSPACE_TIMEOUT);
await projectTree.openProjectTreeContainer();
await projectTree.waitProjectImported(projectName, workspaceRootFolderName);
});
});
});

suite('Language server validation', async () => {
test('Java LS initialization', async () => {
await projectTree.expandPathAndOpenFile(pathToJavaFolder, javaFileName);
await ide.waitNotificationAndClickOnButton('The workspace contains Java projects. Would you like to import them?', 'Yes');
await editor.selectTab(javaFileName);
try {
await ide.checkLsInitializationStart('Activating Language Support for Java');
await ide.waitStatusBarTextAbsence('Activating Language Support for Java', 900_000);
} catch (err) {
if (!(err instanceof error.TimeoutError)) {
throw err;
}

console.log('Known flakiness has occurred https://github.com/eclipse/che/issues/17864');
await ide.waitStatusBarContains('Activating Java Test Runner');
await ide.waitStatusBarTextAbsence('Activating Java Test Runner', 900_000);
}

await checkJavaPathCompletion();
});

test('Autocomplete', async () => {
await editor.moveCursorToLineAndChar(javaFileName, 32, 17);
await editor.pressControlSpaceCombination(javaFileName);
await editor.waitSuggestionContainer();
await editor.waitSuggestion(javaFileName, 'SpringApplication - org.springframework.boot');
});

test('Error highlighting', async () => {
await driverHelper.getDriver().sleep(TimeoutConstants.TS_SUGGESTION_TIMEOUT); // workaround https://github.com/eclipse/che/issues/19004

const textForErrorDisplaying: string = '$';
await editor.type(javaFileName, textForErrorDisplaying, 30);

try {
await editor.waitErrorInLine(30, TimeoutConstants.TS_ERROR_HIGHLIGHTING_TIMEOUT);
} catch (err) {
Logger.debug('Workaround for the https://github.com/eclipse/che/issues/18974.');
await browserTabsUtil.refreshPage();
await ide.waitAndSwitchToIdeFrame();
await ide.waitIde();
await editor.waitErrorInLine(30, TimeoutConstants.TS_ERROR_HIGHLIGHTING_TIMEOUT * 2);
}
await editor.performKeyCombination(javaFileName, Key.chord(Key.BACK_SPACE));
await editor.waitErrorInLineDisappearance(30);
});

test('Suggestion', async () => {
await editor.moveCursorToLineAndChar(javaFileName, 32, 21);
await editor.pressControlSpaceCombination(javaFileName);
await editor.waitSuggestionWithScrolling(javaFileName, 'run(Class<?> primarySource, String... args) : ConfigurableApplicationContext', 120_000);
});

test('Codenavigation', async () => {
await editor.moveCursorToLineAndChar(javaFileName, 32, 17);
await editor.performKeyCombination(javaFileName, Key.chord(Key.CONTROL, Key.F12));
await editor.waitEditorAvailable(codeNavigationClassName, TimeoutConstants.TS_EDITOR_TAB_INTERACTION_TIMEOUT * 4);
});
});
suite('Validation of workspace build and run', async () => {
test('Build application', async () => {
const taskName: string = 'build';
await topMenu.runTask(`${taskName}, ${globalTaskScope}`);
await terminal.waitIconSuccess(taskName, 500_000);
});

test('Run application', async () => {
const taskName: string = 'run';
await topMenu.runTask(`${taskName}, ${globalTaskScope}`);
await ide.waitNotification('Process 8080-tcp is now listening on port 8080. Open it ?', 120_000);
await ide.clickOnNotificationButton('Process 8080-tcp is now listening on port 8080. Open it ?', 'Open In New Tab');
});

test('Check the running application', async () => {
await switchAppWindowAndCheck(SpringAppLocators.springTitleLocator);
});

test('Close the terminal running tasks', async () => {
await terminal.rejectTerminalProcess('run');
await terminal.closeTerminalTab('run');
await warningDialog.waitAndCloseIfAppear();
await terminal.closeTerminalTab('build');
});
});

async function checkJavaPathCompletion() {
if (await ide.isNotificationPresent('Classpath is incomplete. Only syntax errors will be reported')) {
const classpathText: string = fs.readFileSync('./files/happy-path/petclinic-classpath.txt', 'utf8');
const workaroundReportText: string = '\n############################## \n\n' +
'Known issue: https://github.com/eclipse/che/issues/13427 \n' +
'\"Java LS \"Classpath is incomplete\" warning when loading petclinic\" \n' +
'\".classpath\" will be configured with next settings: \n\n' +
classpathText + '\n' +
'############################## \n';

console.log(workaroundReportText);

await projectTree.expandPathAndOpenFile(projectName, classPathFilename);
await editor.waitEditorAvailable(classPathFilename);
await editor.type(classPathFilename, Key.chord(Key.CONTROL, 'a'), 1);
await editor.performKeyCombination(classPathFilename, Key.DELETE);
await editor.type(classPathFilename, classpathText, 1);
await editor.waitTabWithSavedStatus(classPathFilename);
}
}

// when we use devfile v.2 the test app. is opened in the separate window instead of widget
async function switchAppWindowAndCheck(contentLocator: By) {
const mainWindowHandle: string = await browserTabsUtil.getCurrentWindowHandle();
await browserTabsUtil.waitAndSwitchToAnotherWindow(mainWindowHandle, TimeoutConstants.TS_EDITOR_TAB_INTERACTION_TIMEOUT);
const isApplicationTitleVisible: boolean = await driverHelper.isVisible(contentLocator);
if (!isApplicationTitleVisible) {
await driverHelper.getDriver().sleep(TimeoutConstants.TS_SELENIUM_DIALOG_WIDGET_TIMEOUT);
await driverHelper.getDriver().navigate().refresh();
await browserTabsUtil.switchToWindow(mainWindowHandle);
await ide.waitAndSwitchToIdeFrame();
}
}