-
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 "Start a Workspace from a devfile" step from "Happy path" scenario #13479
Conversation
e2e/pageobjects/ide/Editor.ts
Outdated
@@ -13,44 +13,74 @@ import { DriverHelper } from '../../utils/DriverHelper'; | |||
import { CLASSES } from '../../inversify.types'; | |||
import { TestConstants } from '../../TestConstants'; | |||
import { By, Key } from 'selenium-webdriver'; | |||
import { error } from 'selenium-webdriver'; |
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 can be appended to the upper row as import { By, Key, error } from 'selenium-webdriver';
e2e/pageobjects/ide/Editor.ts
Outdated
await this.driverHelper.waitVisibility(By.css(Editor.SUGGESTION_WIDGET_BODY_CSS), timeout); | ||
} | ||
|
||
async waitSuggestionContainerClosed(attempts: number = TestConstants.TS_SELENIUM_DEFAULT_ATTEMPTS, polling: number = TestConstants.TS_SELENIUM_DEFAULT_POLLING) { | ||
await this.driverHelper.waitDisappearance(By.css(Editor.SUGGESTION_WIDGET_BODY_CSS), attempts, polling); | ||
public async waitSuggestionContainerClosed(attempts: number = TestConstants.TS_SELENIUM_DEFAULT_ATTEMPTS, |
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 suggest to remove parameters ' attempts ' and ' polling ' as they are not used.
|
||
await this.pressEscapeButton(editorTabTitle); | ||
await this.waitSuggestionContainerClosed(); | ||
await this.pressControlSpaceCombination(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.
NOTE 1: If I understand correctly reason of this is - if the suggestion is not shown, test tries to view it by pressing ctrl + space
. Shouldn't there be another check if the suggestion is shown correctly for that second attempt?
NOTE 2: Why does pressing ctrl + space
have own method? Why not to call performKeyCombination
directly from 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.
Answer 1: Not exactly. Described logic encapsulated in the "wait" method, this is a kind of loop, it will repeat until called method returns some value, or timeout end.
await this.waitSuggestionContainer();
try {
await this.driverHelper.waitVisibility(suggestionLocator, 5000);
return true;
} catch (err) {
const isTimeoutError: boolean = err instanceof error.TimeoutError;
if (!isTimeoutError) {
throw err;
}
await this.pressEscapeButton(editorTabTitle);
await this.waitSuggestionContainerClosed();
await this.pressControlSpaceCombination(editorTabTitle);
}
Answer 2: It looks much better for me to use particular method for invoking suggestion container than repeat each time this.performKeyCombination(editorTabTitle, Key.chord(Key.CONTROL, Key.SPACE))
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.
Answer 2: You still need to write a line of code - even performKeyCombination or pressControlSpaceCombination. It is quite weird to have methods that contain only one line this way. And it doesn't seem to be frequent method - only 2 usages. The escapeButton
is called only once.
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 must say, that I'm not really fond of this approach either. Maybe if these "typical" key combinations would live in separate classes, then it would be ok. But having such methods in Editor class is not very nice IMO.
But I don't want to block this PR because of this.
throw err; | ||
} | ||
|
||
await this.pressEscapeButton(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.
Why not to call performKeyCombination
directly from 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.
Answer 2 #13479 (comment)
ci-build |
…cenario Signed-off-by: Ihor Okhrimenko <iokhrime@redhat.com>
c1a143f
to
60b1e89
Compare
ci-build |
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 to this PR.
We've also had meeting to discuss more possible changes, but those will be done in separate PR.
e2e/driver/CheReporter.ts
Outdated
}); | ||
} | ||
}); | ||
const isReportDirExist: boolean = fs.existsSync(reportDirPath); |
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.
reportDirExists
would be better name IMO.
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 am guided by "Java" code conduct which pointed that "is" prefix should be used for boolean variables and methods. Is it the right convention for "Typescript"?
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'm not aware of such convention... Even in java it's usual to have different prefixes like has<Property>
, should<beAbleToDoSomething>
, ... Basically anything meaningfull is better, than something not making sense (in this case two verbs in one "sentence"(var name))
Anyway... looking at this code I don't see this variable used anywhere else, so maybe put the fs.existsSync()
directly into the condition?
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.
On my opinion this is
const reportDirExists: boolean = fs.existsSync(reportDirPath);
if (!reportDirExists) {
fs.mkdirSync(reportDirPath);
}
more clear then
if (!fs.existsSync(reportDirPath)) {
fs.mkdirSync(reportDirPath);
}
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.
Let's agree to disagree on the approach :-D What about the name?
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 =)
e2e/driver/CheReporter.ts
Outdated
} | ||
|
||
// create dir for failed test report if not exist | ||
const isTestReportDirExist: boolean = fs.existsSync(testReportDirPath); |
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.
testReportDirExists
would be better name IMO.
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 can see this pattern in more places in this PR, so I won't comment it any further, but the objection still holds ;-)
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.
} | ||
|
||
async waitSuggestion(suggestionText: string, timeout: number = TestConstants.TS_SELENIUM_DEFAULT_TIMEOUT) { | ||
await this.driverHelper.waitVisibility(By.xpath(this.getSuggestionLineXpathLocator(suggestionText)), timeout); | ||
public async waitSuggestion(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.
If I understand this correctly, all the methods here are now requiring editor tab title (a.k.a. name of the file opened in this editor?).
Wouldn't it be better to pass that in the constructor? This way we could have multiple instances of editor - the same way, as user can have multiple editors opened.
Doing that we could go even further - having method editor.setFocus()
to set focus to this editor. And maybe even further? Calling the setFocus() every time, when we try to operate with this editor (for example by editor.type()
) to make sure the correct editor is in focus?
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.
Added to issue: #13479 (comment)
|
||
return elementText.search(expectedText) > 0; | ||
if (isTextPresent) { |
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.
Wouldn't simple return isTextPresent
be nicer? ;-)
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.
Not exactly.
Method "wait" waits until some value is returned,
if we return "false" method will pass,
so that's why we need this "if" check and return
value just in case of successful check
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.
For a {@link webdriver.Condition} or function, the wait will repeatedly evaluate the condition until it returns a truthy value.
From this it seems to me, that returning false
should cause the wait loop to be executed again...
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.
You can check it yourself, it works as I described
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... Unfortunately I dont have time to try now, so I believe you :-D
|
||
}, timeout); | ||
if (isTextAbsent) { |
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.
same as with isTextPresent
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.
e2e/pageobjects/ide/Editor.ts
Outdated
}, timeout); | ||
} | ||
|
||
async waitSuccessBuildText(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.
Such specific method shouldn't be here... Instead we should have something like waitForText(editor, text, timeout, polling)
e2e/pageobjects/ide/PreviewWidget.ts
Outdated
await this.driverHelper.waitDisappearance(By.css('div.theia-mini-browser')); | ||
} | ||
|
||
async waitSpringAvailable(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.
Too specific method for page object... Instead of this we should take By
(?) locator, which we should look for inside the preview page object?
return true; | ||
} | ||
|
||
await this.driverHelper.getDriver().switchTo().defaultContent(); |
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 section seems weird to me... Is it some workaround for some problem?
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.
part of the preview widget placed in the iframe
I have created an issue with described required improvements |
Signed-off-by: Ihor Okhrimenko <iokhrime@redhat.com>
Signed-off-by: Ihor Okhrimenko <iokhrime@redhat.com>
e2e/pageobjects/ide/Editor.ts
Outdated
}, timeout); | ||
} | ||
|
||
async waitForText(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.
Hmm... now, the method is called "generally", but it's still waiting for some specific, hard-coded text.
My original suggestion was to rewrite the method to take string parameter (text to wait for).
Now I can also see we already have such method (waitText
), but that one has slightly different logic (it's not scrolling down, as this one).
Maybe this one shoud be renamed&rewritten to something like
followAndWaitForText(editorTabTitle: string, textToSearchFor: string, timeout: number, polling:number)
Signed-off-by: Ihor Okhrimenko <iokhrime@redhat.com>
What does this PR do?
Cover the "Start a Workspace from a devfile" step from "Happy path" scenario
What issues does this PR fix or reference?
Issue: #13356
Release Notes
Docs PR