-
Notifications
You must be signed in to change notification settings - Fork 3.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
chore(server): convert remaining browsers code to typescript #23556
Conversation
Thanks for taking the time to open a PR!
|
Test summaryRun details
View run in Cypress Dashboard ➡️ This comment has been generated by cypress-bot as a result of this project's GitHub integration settings. You can manage this integration in this project's settings in the Cypress Dashboard |
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.
Cool, glad to see more TS, I hope we can get more and more strict. In general
- seems some un-necesary
async
usage - consider
assert
overthrow new Error
(more concise and seems more idiomatic in my experience)
💯
@@ -294,6 +294,7 @@ function startAppServer (mode: 'component' | 'e2e' = 'e2e', options: { skipMocki | |||
if (!ctx.lifecycleManager.browsers?.length) throw new Error('No browsers available in startAppServer') | |||
|
|||
await ctx.actions.browser.setActiveBrowser(ctx.lifecycleManager.browsers[0]) | |||
// @ts-expect-error this interface is strict about the options it expects | |||
await ctx.actions.project.launchProject(o.mode, { url: o.url }) |
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 looks like the interface is
export interface LaunchOpts {
browser?: FoundBrowser
url?: string
automationMiddleware?: AutomationMiddleware
projectRoot?: string
shouldLaunchNewTab?: boolean
onBrowserClose?: (...args: unknown[]) => void
onBrowserOpen?: (...args: unknown[]) => void
onError?:
}
I wonder why we need the ts-expect-error
? What is the 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.
It's only OpenProjectLaunchOpts
at this point, which doesn't have url
. This is an area that should be refactored, we're putting a lot of functionality into project.launchProject
that makes it difficult to reason with (and difficult to sanely type)
debug('connecting to new chrome tab in existing instance with url and debugging port', { url: options.url }) | ||
|
||
const browserCriClient = this._getBrowserCriClient() | ||
|
||
if (!browserCriClient) throw new Error('Missing browserCriClient in connectToNewSpec') |
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 think assert
is more common for this kind of thing, eg
assert(this.ctx.currentProject, `Cannot checkIfFileExists without active project`) |
assert(browserCriClient, 'Missing browserCriClient in connectToNewSpec')
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.
assert
doesn't seem to provide the type guarding needed, which is why I added this conditional. With assert
, I still get browserCriClient is possibly 'undefined'
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 should actually close #22451
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, at least it will give a clearer error message.
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.
Well...it doesn't fix it but it just give a better warning. I remember talking with @ryanthemanuel about this
we close the browser on a retry:
https://github.com/cypress-io/cypress/blob/develop/packages/server/lib/modes/run.js#L1127
but likely don't flip the indicator that tells it to try and launch the browser from scratch
|
||
if (!options.url) throw new Error('Missing url in connectToNewSpec') | ||
|
||
await this.attachListeners(browser, options.url, pageCriClient, automation, options) |
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.
Instead of marking this as asyncand doing
await this.attachListenershould we just remove
asyncand then
return this.attachListeners? It looks like we do
awaitwhere we call this function so marking it as
asyncand then calling
await` at the end doesn't seem to do anything.
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.
Readability-wise, I prefer await
ing a Promise over return
ing it, because it makes it obvious you're doing an asynchronous operation at the "end" of the function.
options = Windows.defaults(options) | ||
// get our electron default options | ||
// TODO: this is bad, don't mutate the options object | ||
options = this._defaultOptions(projectRoot, state, options, automation) |
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 agree mutation is the main thing that makes server so damn hard to work in :(
|
||
if (browser.name === 'electron') { | ||
return require('./electron') | ||
return require('./electron') as typeof import('./electron') |
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 sure if this breaks things but should be able to do something like (I think)
return await import('./electron')
And get typing without as typeof
. Also good to standardize on one syntax. Then getBrowserLauncher
will return a Promise
and well need to be awaited, though.
Or, we can just do
import chrome from './chrome'
Etc all at the top - not sure if there's any performance implication here, but moving towards proper ESM seems like a good idea, so maybe one day we can ship native ESM instead of CommonJS (although this is likely many years away, it would still be nice to work towards it).
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.
Since each browser requires different dependencies, it's done this way for performance. Whether or not it makes a big (or indeed, positive) impact... I'm not sure, but I'm not going to refactor the lazy-loading in this PR. I did switch to await import: ce15192
isProcessExit?: boolean | ||
} | ||
|
||
export type BrowserLauncher = { |
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.
Yay, standardize browser launching interface, nice,
Windows.removeAllExtensions(win) | ||
|
||
return Bluebird.map(extensionPaths, (extensionPath) => { | ||
return Promise.all(extensionPaths.map((extensionPath) => { |
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.
👍🏻
@@ -679,21 +696,7 @@ export = { | |||
|
|||
const pageCriClient = await browserCriClient.attachToTargetUrl('about:blank') | |||
|
|||
await this._setAutomation(pageCriClient, automation, browserCriClient.resetBrowserTargets, options) |
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 deduping of this code here. Good clean up
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 work. Lots of good clean up here. The only thing I might question (though we do it a lot of places) with the new additional throw
statements, do they fail gracefully or crash the server completely?
@ryanthemanuel All the new |
User facing changelog
Additional details
packages/server/lib/browsers/index.js
to.ts
and adds types for theBrowserLauncher
implementationselectron.js
to.ts
, although I did not spend as much time adding types hereSteps to test
How has the user experience changed?
PR Tasks
cypress-documentation
?type definitions
?