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

chore(server): convert modes/run to typescript #23536

Merged
merged 4 commits into from
Aug 25, 2022
Merged

chore(server): convert modes/run to typescript #23536

merged 4 commits into from
Aug 25, 2022

Conversation

flotwig
Copy link
Contributor

@flotwig flotwig commented Aug 24, 2022

  • Closes

User facing changelog

n/a

Additional details

  • Was working on refactoring the video recording code for Safari (WebKit) Support #6422 and was finally driven insane by the number of floating untyped variables in modes/run.
  • I added types with minimal refactoring - it's still a mess, but it's a typed mess.
  • GitHub's built in diff tool fails to recognize the rename of run.js -> run.ts if you view all changes together. To make it easier to review, here are the distinct commits and what they do:
    • 11ecebd adds types and fixes type errors
    • 98e69d0 removes a unit-level run spec that has not been running for a while now, and has been superseded by e2e/integration tests
    • d06d529 removes all run exports except run() itself. moving everything off of module.exports and this caused new type errors since more type checking took place, this commit fixes those errors.

Steps to test

How has the user experience changed?

PR Tasks

  • Have tests been added/updated?
  • [na] Has the original issue (or this PR, if no issue exists) been tagged with a release in ZenHub? (user-facing changes only)
  • [na] Has a PR for user-facing changes been opened in cypress-documentation?
  • [na] Have API changes been updated in the type definitions?

@cypress-bot
Copy link
Contributor

cypress-bot bot commented Aug 24, 2022

Thanks for taking the time to open a PR!

@cypress
Copy link

cypress bot commented Aug 25, 2022



Test summary

41474 0 1434 0Flakiness 14


Run details

Project cypress
Status Passed
Commit a75ec8a
Started Aug 25, 2022 4:36 PM
Ended Aug 25, 2022 4:52 PM
Duration 16:15 💡
OS Linux Debian - 11.3
Browser Multiple

View run in Cypress Dashboard ➡️


Flakiness

cypress/e2e/commands/net_stubbing.cy.ts Flakiness
1 network stubbing > intercepting request > can delay with deprecated delayMs param
2 network stubbing > intercepting request > can delay with deprecated delayMs param
3 network stubbing > intercepting request > can delay with deprecated delayMs param
4 ... > with `times` > only uses each handler N times
5 network stubbing > intercepting response > can 'delay' a proxy response using Promise.delay
This comment includes only the first 5 flaky tests. See all 14 flaky tests in the 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

no need to import cypress

fix .tap

video fixes

remove wk mention

more async cleanup

fix cypress_spec

fix exitEarly
@@ -338,8 +339,11 @@ describe('lib/cypress', () => {
await clearCtx()

sinon.stub(electron.app, 'on').withArgs('ready').yieldsAsync()
sinon.stub(runMode, 'waitForSocketConnection').resolves()
sinon.stub(runMode, 'listenForProjectEnd').resolves({ stats: { failures: 0 } })
globalThis.CY_TEST_MOCK = {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, I introduced this pattern because we have a lot of integration test coverage here that does deep mocking of (what was previously on) module.exports. I know this is an unfortunate way to handle mocking, but I felt it was the lesser of evils... the other options being to export everything to make it stubbable and call methods off module.exports, or some kinda proxyquire hackery. Open to better ideas here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really question the value of some of these tests, where we mock 90% of the world to test some random method... I almost wonder if we collapse ~100 unit tests into ~5 system tests and just aggressively delete some of these. I think a lot of these are from the days prior to system-tests existing?

If we have really complex unit level logic, stick it in a pure function and unit test that, so we don't need so much mocking/stubbing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. I didn't want to have to dive into figuring out what edge cases are/aren't covered in these integration tests versus other tests for this PR, but we do have way too many tests like this.

sinon.stub(runMode, 'waitForSocketConnection').resolves()

sinon.stub(runMode, 'waitForBrowserToConnect').resolves({
stats: {
Copy link
Contributor Author

@flotwig flotwig Aug 25, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this object stub shape seems to have been a typo, which is why it was removed

}
}

async function runSpecs (options: { config: Cfg, browser: Browser, sys: any, headed: boolean, outputPath: string, specs: SpecWithRelativeRoot[], specPattern: string | RegExp | string[], beforeSpecRun?: BeforeSpecRun, afterSpecRun?: AfterSpecRun, runUrl?: string, parallel?: boolean, group?: string, tag?: string, testingType: TestingType, quiet: boolean, project: Project, onError: (err: Error) => void, exit: boolean, socketId: string, webSecurity: boolean, projectRoot: string } & Pick<Cfg, 'video' | 'videoCompression' | 'videosFolder' | 'videoUploadOnPasses'>) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahhh yes awesome, we need this so desperately. Every time I tried to make this into TS, I realized how much work it was and abandoned it - definitely time well spent to figure out what these types are.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, there's still about 4 billion de-structured variables too many in this file, but at least this will enable us to more confidently refactor in the future.

@flotwig flotwig marked this pull request as ready for review August 25, 2022 01:08
@@ -30,7 +30,7 @@ export interface FullConfig extends Partial<Cypress.RuntimeConfigOptions & Cypre
// and are required when creating a project.
export type ReceivedCypressOptions =
Pick<Cypress.RuntimeConfigOptions, 'hosts' | 'projectName' | 'clientRoute' | 'devServerPublicPathRoute' | 'namespace' | 'report' | 'socketIoCookie' | 'configFile' | 'isTextTerminal' | 'isNewProject' | 'proxyUrl' | 'browsers' | 'browserUrl' | 'socketIoRoute' | 'arch' | 'platform' | 'spec' | 'specs' | 'browser' | 'version' | 'remote'>
& Pick<Cypress.ResolvedConfigOptions, 'chromeWebSecurity' | 'supportFolder' | 'experimentalSourceRewriting' | 'fixturesFolder' | 'reporter' | 'reporterOptions' | 'screenshotsFolder' | 'supportFile' | 'baseUrl' | 'viewportHeight' | 'viewportWidth' | 'port' | 'experimentalInteractiveRunEvents' | 'userAgent' | 'downloadsFolder' | 'env' | 'excludeSpecPattern' | 'specPattern' | 'experimentalSessionAndOrigin' | 'experimentalModifyObstructiveThirdPartyCode'> // TODO: Figure out how to type this better.
& Pick<Cypress.ResolvedConfigOptions, 'chromeWebSecurity' | 'supportFolder' | 'experimentalSourceRewriting' | 'fixturesFolder' | 'reporter' | 'reporterOptions' | 'screenshotsFolder' | 'supportFile' | 'baseUrl' | 'viewportHeight' | 'viewportWidth' | 'port' | 'experimentalInteractiveRunEvents' | 'userAgent' | 'downloadsFolder' | 'env' | 'excludeSpecPattern' | 'specPattern' | 'experimentalSessionAndOrigin' | 'experimentalModifyObstructiveThirdPartyCode' | 'video' | 'videoCompression' | 'videosFolder' | 'videoUploadOnPasses' | 'resolvedNodeVersion' | 'resolvedNodePath' | 'trashAssetsBeforeRuns'> // TODO: Figure out how to type this better.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One day this will be Pick<all the things>. I wonder if this is useful? I think I wrote this originally, when it had like 2-3 properties in Pick... it's growing with every PR!

I think the original intent was "These are the options we use in this part of the code" but we might have outgrown it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I was questioning this also. It doesn't seem like we would have only some ResolvedConfigOptions and not others at any point.

Copy link
Contributor

@lmiller1990 lmiller1990 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this - I know it's still draft but going to follow along, this will have very high long term value - working in run.js is kind of like stumbling around in the dark at the moment :|

@flotwig flotwig requested a review from lmiller1990 August 25, 2022 01:12
Copy link
Contributor

@tbiethman tbiethman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. I'll second the thanks for this, it will be a big help going forward.

@@ -46,7 +47,7 @@ export interface AutomationMiddleware {
onBeforeRequest?: OnRequestEvent | null
onRequest?: OnRequestEvent | null
onResponse?: NullableMiddlewareHook
onAfterResponse?: NullableMiddlewareHook
onAfterResponse?: ((eventName: string, data: any, resp: any) => void) | null
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be nice if we someday remove the null states and leveraged undefined

// electron >= 5.0.0 will exit the app if all browserwindows are closed,
// this is obviously undesirable in run mode
// https://github.com/cypress-io/cypress/pull/4720#issuecomment-514316695
app.on('window-all-closed', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this is still true

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it should be. This was an intentional change, since most Electron apps should have 0 processes left when all the windows are closed. We're the exception to their rule

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@flotwig flotwig merged commit bd0d38f into develop Aug 25, 2022
@flotwig flotwig deleted the ts-run-mode branch August 25, 2022 17:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants