-
Notifications
You must be signed in to change notification settings - Fork 5.9k
refactor(testing): fix flaky terminal test #3230
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ import { CODE_SERVER_ADDRESS } from "../../utils/constants" | |
// See Playwright docs: https://playwright.dev/docs/pom/ | ||
export class CodeServer { | ||
page: Page | ||
editorSelector = "div.monaco-workbench" | ||
|
||
constructor(page: Page) { | ||
this.page = page | ||
|
@@ -30,15 +31,18 @@ export class CodeServer { | |
// but usually a reload or two fixes it | ||
// TODO@jsjoeio @oxy look into Firefox reconnection/timeout issues | ||
while (!editorIsVisible) { | ||
// When a reload happens, we want to wait for all resources to be | ||
// loaded completely. Hence why we use that instead of DOMContentLoaded | ||
// Read more: https://thisthat.dev/dom-content-loaded-vs-load/ | ||
await this.page.waitForLoadState("load") | ||
// Give it an extra second just in case it's feeling extra slow | ||
await this.page.waitForTimeout(1000) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ahah these things make me sad, totally fair though There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. lol i know. sadly, this timeout was the only thing that made it consistently pass. |
||
reloadCount += 1 | ||
if (await this.isEditorVisible()) { | ||
console.log(` Editor became visible after ${reloadCount} reloads`) | ||
break | ||
} | ||
// When a reload happens, we want to wait for all resources to be | ||
// loaded completely. Hence why we use that instead of DOMContentLoaded | ||
// Read more: https://thisthat.dev/dom-content-loaded-vs-load/ | ||
await this.page.reload({ waitUntil: "load" }) | ||
await this.page.reload() | ||
} | ||
} | ||
|
||
|
@@ -49,46 +53,39 @@ export class CodeServer { | |
// Make sure the editor actually loaded | ||
// If it's not visible after 5 seconds, something is wrong | ||
await this.page.waitForLoadState("networkidle") | ||
return await this.page.isVisible("div.monaco-workbench", { timeout: 5000 }) | ||
return await this.page.isVisible(this.editorSelector) | ||
} | ||
|
||
/** | ||
* Focuses Integrated Terminal | ||
* by going to the Application Menu | ||
* and clicking View > Terminal | ||
* by using "Terminal: Focus Terminal" | ||
* from the Command Palette | ||
* | ||
* This should focus the terminal no matter | ||
* if it already has focus and/or is or isn't | ||
* visible already. | ||
*/ | ||
async focusTerminal() { | ||
// If the terminal is already visible | ||
// then we can focus it by hitting the keyboard shortcut | ||
const isTerminalVisible = await this.page.isVisible("#terminal") | ||
if (isTerminalVisible) { | ||
await this.page.keyboard.press(`Control+Backquote`) | ||
// Wait for terminal to receive focus | ||
await this.page.waitForSelector("div.terminal.xterm.focus") | ||
// Sometimes the terminal reloads | ||
// which is why we wait for it twice | ||
await this.page.waitForSelector("div.terminal.xterm.focus") | ||
return | ||
} | ||
// Open using the manu | ||
// Click [aria-label="Application Menu"] div[role="none"] | ||
await this.page.click('[aria-label="Application Menu"] div[role="none"]') | ||
|
||
// Click text=View | ||
await this.page.hover("text=View") | ||
await this.page.click("text=View") | ||
|
||
// Click text=Terminal | ||
await this.page.hover("text=Terminal") | ||
await this.page.click("text=Terminal") | ||
// Click text=Command Palette | ||
await this.page.hover("text=Command Palette") | ||
await this.page.click("text=Command Palette") | ||
|
||
// Type Terminal: Focus Terminal | ||
await this.page.keyboard.type("Terminal: Focus Terminal") | ||
|
||
// Click Terminal: Focus Terminal | ||
await this.page.hover("text=Terminal: Focus Terminal") | ||
await this.page.click("text=Terminal: Focus Terminal") | ||
Comment on lines
+76
to
+85
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This approach produces consistent results — no matter if the terminal is already focused, visible/not visible. |
||
|
||
// Wait for terminal to receive focus | ||
// Sometimes the terminal reloads once or twice | ||
// which is why we wait for it to have the focus class | ||
await this.page.waitForSelector("div.terminal.xterm.focus") | ||
// Sometimes the terminal reloads | ||
// which is why we wait for it twice | ||
await this.page.waitForSelector("div.terminal.xterm.focus") | ||
// Wait for terminal textarea to show up | ||
await this.page.waitForSelector("textarea.xterm-helper-textarea") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This also seems to be better than looking for the H/T to @kylecarbs for the suggestion 🎉 |
||
} | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,6 +52,8 @@ test.describe("Integrated Terminal", () => { | |
await page.waitForLoadState("load") | ||
await page.keyboard.type(`echo '${testString}' > '${tmpFile}'`) | ||
await page.keyboard.press("Enter") | ||
// It may take a second to process | ||
await page.waitForTimeout(1000) | ||
Comment on lines
+55
to
+56
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is no great way of knowing that the terminal received both the input and the enter and processed it (because it's a |
||
|
||
const { stdout } = await output | ||
expect(stdout).toMatch(testString) | ||
|
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 realized how many places I was using this in the model so refactored it into a property of the class