-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
[TS-SELENIUM] Cover the "Use Java IDE features and the inner loop" step from "Happy path" scenario #13615
Conversation
ci-build |
ci-build |
22c8bc6
to
bdcb8c7
Compare
… path' scenario Signed-off-by: Ihor Okhrimenko <iokhrime@redhat.com>
bdcb8c7
to
9575e3c
Compare
ci-build |
Signed-off-by: Ihor Okhrimenko <iokhrime@redhat.com>
Signed-off-by: Ihor Okhrimenko <iokhrime@redhat.com>
Signed-off-by: Ihor Okhrimenko <iokhrime@redhat.com>
Signed-off-by: Ihor Okhrimenko <iokhrime@redhat.com>
Signed-off-by: Ihor Okhrimenko <iokhrime@redhat.com>
Signed-off-by: Ihor Okhrimenko <iokhrime@redhat.com>
Signed-off-by: Ihor Okhrimenko <iokhrime@redhat.com>
Signed-off-by: Ihor Okhrimenko <iokhrime@redhat.com>
Signed-off-by: Ihor Okhrimenko <iokhrime@redhat.com>
Signed-off-by: Ihor Okhrimenko <iokhrime@redhat.com>
e2e/pageobjects/ide/Editor.ts
Outdated
async closeTab(tabTitle: string, timeout: number = TestConstants.TS_SELENIUM_DEFAULT_TIMEOUT) { | ||
const tabCloseButtonLocator: By = By.xpath(`//div[text()='${tabTitle}']/parent::li//div[contains(@class, 'p-TabBar-tabCloseIcon')]`); | ||
const tabCloseButtonLocator: By = this.getTabCloseIconLocator(tabTitle); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is the logic moved to method which is used only once?
e2e/pageobjects/ide/Editor.ts
Outdated
}, timeout); | ||
} | ||
|
||
public async waitHighlightedSuggestion(editorTabTitle: string, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is not used.
e2e/pageobjects/ide/Editor.ts
Outdated
@@ -140,9 +187,13 @@ export class Editor { | |||
timeout: number = TestConstants.TS_SELENIUM_DEFAULT_TIMEOUT, | |||
polling: number = TestConstants.TS_SELENIUM_DEFAULT_POLLING) { | |||
|
|||
await this.ide.closeAllNotifications(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would move this.ide.closeAllNotifications()
to the method selectTab
and use this method here instead of current code. So from currently:
await this.ide.closeAllNotifications();
await this.clickOnTab(editorTabTitle);
await this.waitTabFocused(editorTabTitle);
I would call await this.selectTab(editorTabTitle);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The selectTab
method has been already implemented. Just put it here.
e2e/pageobjects/ide/Editor.ts
Outdated
} | ||
|
||
if (err instanceof error.WebDriverError) { | ||
await this.driverHelper.wait(polling); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why should we wait when WebDriverError occures?
export class Terminal { | ||
constructor(@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper) { } | ||
|
||
async waitTab(tabTitle: string, timeout: number = TestConstants.TS_SELENIUM_DEFAULT_TIMEOUT) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some of the methods like waitTab
or closeTab
seems to be same as those in Editor. Maybe it would be better to move them to some another class to avoid code duplication.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Editor & terminal are two different "parts of IDE"... they may have these methods in common, but I don't think it would be wise to abstract this (make a common ancestor for these components), as these components are not very related....
}); | ||
}); | ||
|
||
suite.skip('Language server validation', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the skip there intended?
await driverHelper.wait(5000); | ||
|
||
// await topMenu.selectOption('Terminal', 'Run Task...'); | ||
// await quickOpenContainer.clickOnContainerItem('che: run'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are those comments left there?
const attempts: number = TestConstants.TS_SELENIUM_DEFAULT_ATTEMPTS; | ||
const polling: number = TestConstants.TS_SELENIUM_DEFAULT_POLLING; | ||
|
||
for (let i = 0; i < attempts; i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please elaborate why await with timeout is not suitable and you have to use for loop here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because timeout assumes that wait will be failed when the timeout end. And try may be not repeated if waiting for the element is too long. In this case, I want to ensure that try will be repeated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the possible solution could be reduce the timeout for waiting for the elements inside the "waiting function" and increasing timeout for the wait, right? But yeah... As you mentioned under my comment here.. this could be done in other PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've put some comments in here... Most of them are not blocking the PR, but I would like to have some reaction to them before merging the PR.
Also what I'm missing, when reading and - more importantly - running the tests is proper logging. I would like to know what is happening... The most obvious examples are the waiting functions... I would like to see in the logs what is currently being executed, how long are we waiting for different stuff etc. But this is something we would need to tackle in some other PR.
@@ -112,3 +112,6 @@ data: | |||
JAEGER_SAMPLER_PARAM: "1" | |||
JAEGER_REPORTER_MAX_QUEUE_SIZE: "10000" | |||
CHE_METRICS_ENABLED: {{ .Values.global.metricsEnabled | quote }} | |||
CHE_WORKSPACE_JAVA__OPTIONS: "-Xmx2000m" | |||
CHE_WORKSPACE_MAVEN__OPTIONS: "-Xmx20000m" | |||
CHE_INFRA_KUBERNETES_WORKSPACE__START__TIMEOUT__MIN: "15" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have we tried that without this timeout? (Just with default one?) I would prefer having default one and put this extended one just in case the default proves to be not sufficient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without this variables each launch fails with "heap space" error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I may have not been completely clear here... I was talking just about CHE_INFRA_KUBERNETES_WORKSPACE__START__TIMEOUT__MIN
. This one is not affecting command execution (build inside workspace) in any way.
|
||
// take browser console logs and write to file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice addition. +1 ;-)
e2e/pageobjects/ide/DebugView.ts
Outdated
const configurationItemLocator: By = By.xpath(`//select[@class='debug-configuration']//option[text()=\'${itemText}\']`); | ||
|
||
// for ensure that drop-down list has been opened | ||
await this.driverHelper.wait(2000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't these "hard" waits be replaced by some conditional waits? I think having "dumb" sleeps in test code is not a good practice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case, it is not critical because it works properly even without this sleep. This is my overcautiousness for CI launches
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I strongly believe any sleep like this should be either removed, or replaced by conditional wait.
These three waits in this method are perfect example of this... You even put into comments what should we wait for.
This is the strongest reason preventing me from giving approval to this PR. If it works OK without them (even on CI), we could remove them. If it doesn't work right without them, we should replace them with conditional waits.
e2e/pageobjects/ide/Editor.ts
Outdated
return true; | ||
} catch (err) { | ||
const isTimeoutError: boolean = err instanceof error.TimeoutError; | ||
if (!isTimeoutError) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hehe.. just a nitpicking:
if (! (err instanceof error.TimeoutError)) {
throw err;
}
This version seems readable enough for me without needing to create new variable. This is not blocking this PR at all, I'm just expressing my opinion ;-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, I used this variable for debug logging, logging was removed and the variable is left
return; | ||
} catch (err) { | ||
// ignore errors and wait | ||
await this.driverHelper.wait(polling); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we know what errors can happen here? Shouldn't we at least log them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case, we should ignore all exceptions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah.. I can see that from the code, that we are ignoring all the errors... My question was "Why?"
I'm not saying this "silent swallowing" of errors have to be wrong. But usually it's a bad code smell and I think it needs more explanation.
Furthermore, there is quite a big chunk (relatively) of code in the try-catch block and I can imagine quite lot of possible errors could happen - having them logged could help in possible debugging.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because actions inside of try/catch are very sensitive, and I tried to process most common exceptions and final was that the "WebDriverError" may be happening and it does not make sense to process other exceptions because it is a parent of all driver exceptions. Anyway, if something went wrong exception with full explanation will be thrown in the further code.
await editor.waitTabFocused(javaFileName); | ||
await editor.selectTab(javaFileName); | ||
|
||
await ide.checkLsInitializationStart('Starting Java Language Server'); | ||
await ide.waitStatusBarTextAbcence('Starting Java Language Server', 360000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this is out of scope of this PR, but for some next time - Abcence
doesn't exist - it's Absence
} | ||
} | ||
|
||
// async function runTask(taskTitle: string, terminalTabTitle: string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some forgotten commented code. Pls remove this from the final PR.
const attempts: number = TestConstants.TS_SELENIUM_DEFAULT_ATTEMPTS; | ||
const polling: number = TestConstants.TS_SELENIUM_DEFAULT_POLLING; | ||
|
||
for (let i = 0; i < attempts; i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know you have already lot of methods like this, where you implemented your polling mechanism, but is this really needed? Couldn't we just use https://github.com/SeleniumHQ/selenium/blob/master/javascript/node/selenium-webdriver/lib/webdriver.js#L448? (and as allways... I'm pretty new to this tech, so there may be reasons for this to be not possible... If yes, please tell me the reasons - I want to get wiser :-D)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar question and ansver #13615 (comment) .
And a small addition. Most of the mentioned methods really maybe reworked by waits. I have already done something similar https://github.com/eclipse/che/blob/master/e2e/utils/DriverHelper.ts#L150-L170
It may be done in the separate PR
Signed-off-by: Ihor Okhrimenko <iokhrime@redhat.com>
Signed-off-by: Ihor Okhrimenko <iokhrime@redhat.com>
Signed-off-by: Ihor Okhrimenko <iokhrime@redhat.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've put some more comments here... I'm also requesting changes, as I feel strongly about "hard sleeps" ( like driverHelper.wait(2000)
).
components: | ||
- type: kubernetes | ||
alias: petclinic-web | ||
reference: https://gist.githubusercontent.com/l0rd/52eda1d1b57878a218cba17c0c93a477/raw/9a2d56e777d22e77c25c45744caea35bb62d8688/petclinic.yaml |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's possible to have URL to raw file also by branch.. that may be better solution to this.
https://raw.githubusercontent.com/eclipse/che/master/e2e/files/happy-path/containers-happy-path.yaml
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking about it more... I guess this will come in followup PR, right? (To not break current state)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Already changed locally to the branch URL
return; | ||
} catch (err) { | ||
// ignore errors and wait | ||
await this.driverHelper.wait(polling); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah.. I can see that from the code, that we are ignoring all the errors... My question was "Why?"
I'm not saying this "silent swallowing" of errors have to be wrong. But usually it's a bad code smell and I think it needs more explanation.
Furthermore, there is quite a big chunk (relatively) of code in the try-catch block and I can imagine quite lot of possible errors could happen - having them logged could help in possible debugging.
elementStyleValue = elementStyleValue.replace('position: absolute; top: ', ''); | ||
elementStyleValue = elementStyleValue.replace('px; width: 100%; height: 19px;', ''); | ||
|
||
const lineYCoordinate: number = Number.parseInt(elementStyleValue, 10); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Ohrimenko1988 Would be nice to respond even if you don't agree with the proposed solution ;-) I, for example, think the regexp solution is a bit more robust... If you think it's not needed to have more robust solution, please respond ;-)
await this.driverHelper.getDriver().wait(async () => { | ||
const elementText: string = await this.driverHelper.waitAndGetText(statusBarLocator, timeout); | ||
// for ensuring that check is not invoked in the gap of status displaying | ||
for (let i: number = 0; i < 3; i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Ohrimenko1988 Explanation? I genuinely don't understand this piece of code and it doesn't make much sense to me...
@@ -112,3 +112,6 @@ data: | |||
JAEGER_SAMPLER_PARAM: "1" | |||
JAEGER_REPORTER_MAX_QUEUE_SIZE: "10000" | |||
CHE_METRICS_ENABLED: {{ .Values.global.metricsEnabled | quote }} | |||
CHE_WORKSPACE_JAVA__OPTIONS: "-Xmx2000m" | |||
CHE_WORKSPACE_MAVEN__OPTIONS: "-Xmx20000m" | |||
CHE_INFRA_KUBERNETES_WORKSPACE__START__TIMEOUT__MIN: "15" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I may have not been completely clear here... I was talking just about CHE_INFRA_KUBERNETES_WORKSPACE__START__TIMEOUT__MIN
. This one is not affecting command execution (build inside workspace) in any way.
e2e/pageobjects/ide/DebugView.ts
Outdated
const configurationItemLocator: By = By.xpath(`//select[@class='debug-configuration']//option[text()=\'${itemText}\']`); | ||
|
||
// for ensure that drop-down list has been opened | ||
await this.driverHelper.wait(2000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I strongly believe any sleep like this should be either removed, or replaced by conditional wait.
These three waits in this method are perfect example of this... You even put into comments what should we wait for.
This is the strongest reason preventing me from giving approval to this PR. If it works OK without them (even on CI), we could remove them. If it doesn't work right without them, we should replace them with conditional waits.
export class Terminal { | ||
constructor(@inject(CLASSES.DriverHelper) private readonly driverHelper: DriverHelper) { } | ||
|
||
async waitTab(tabTitle: string, timeout: number = TestConstants.TS_SELENIUM_DEFAULT_TIMEOUT) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Editor & terminal are two different "parts of IDE"... they may have these methods in common, but I don't think it would be wise to abstract this (make a common ancestor for these components), as these components are not very related....
e2e/pageobjects/ide/Terminal.ts
Outdated
await this.selectTerminalTab(tabTitle, timeout); | ||
|
||
// for ensure that element is interactable | ||
await this.driverHelper.wait(3000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this is still something I strongly feel about... Until I'm proven we really need this and it couldn't be done any other way I would request this to change.
Signed-off-by: Ihor Okhrimenko <iokhrime@redhat.com>
Signed-off-by: Ihor Okhrimenko <iokhrime@redhat.com>
Signed-off-by: Ihor Okhrimenko <iokhrime@redhat.com>
Signed-off-by: Ihor Okhrimenko <iokhrime@redhat.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are still some questions/nitpicks unanswered, but all of them are of minor character.
What does this PR do?
Cover the "Use Java IDE features and the inner loop" step from "Happy path" scenario
What issues does this PR fix or reference?
Issue: #13519
Release Notes
Docs PR